I want to add a link to each element of an array, then join the resulting array. I tried:
myarray.collect{|u| link_to u[:first_name], username_path(u[:username])}.join(', ')
This does everything correctly, except it returns:
<a href="/niels">Niels Bohr</a>, <a href="/richard">Richard Feynman</a>
Instead of
Niels Bohr, Richard Feynman
How do I fix this? Or is there a simpler way of proceeding?
Thanks.
Use html_safe
myarray.collect{|u| link_to u[:first_name], username_path(u[:username])}.join(', ').html_safe
There is nothing wrong with adding the links or joining the elements of the list. That all works fine. What is wrong is that your string is considered unsafe and some of the characters used to construct valid HTML (and more importantly, javascript) are being escaped.
As fl00r says, you should add
.html_safe after the string, to tell the rendering function that any HTML in the function can be safely sent to the browser as-is.
Related
I've read in multiple places that as of Rails 3 you no longer have to use html_escape "some string" to actually escape a string in a view and that simply writing <%= "some string" %> would escape the string by default. However, I cannot find this information in the docs. I read through the XSS in the Rails guides section that stated this:
https://guides.rubyonrails.org/security.html#cross-site-scripting-xss
As a second step, it is good practice to escape all output of the application, especially when re-displaying user input, which hasn't been input-filtered (as in the search form example earlier on). Use escapeHTML() (or its alias h()) method to replace the HTML input characters &, ", <, and > by their uninterpreted representations in HTML (&, ", <, and >).
Then I see several blogs that state that it is escaped by default. For example: https://www.netsparker.com/blog/web-security/preventing-xss-ruby-on-rails-web-applications/
https://dzone.com/articles/preventing-cross-site-scripting-vulnerabilities-wh
Found it:
https://guides.rubyonrails.org/3_0_release_notes.html
"7.4.3 Other Changes
You no longer need to call h(string) to escape HTML output, it is on by default in all view templates. If you want the unescaped string, call raw(string)."
escapeHTML() (or its alias h()) are from CGI::escapeHTML, which is a Ruby API implementation. If you aren't using Rails you still have a way to escape HTML. Rails may do some automagical handling of HTML in ERB files for display, and that is what you are probably referring to with html_escape "some string" and <%= "some string" %>. I think you are possibly confusing html_escape which you might need when displaying urls and such that are stored in the DB and you want the ERB processor to not mess it up? I know sometimes, particularly in .js.erb files I need to escape some things to get the result I was expecting. This is different than sanitizing. It seems in your example they are referring to something that you might accept and then redisplay, like a search string. If you put <i>hello</i> into a search box you would want to sanitize the input before passing it to the back end, or if you are using some javascript to filter you might want to escape it both for security reasons and to let it re-display correctly in the search box after you've filtered.
Edit: I was not able to find the answer to your comment in the ri doc either. But I tried:
<%= "<b>hello</b>" %>
<%= h("<b>hello</b>") %>
And got the same result in the browser:
<b>hello</b>
<b>hello</b>
So if you are asking if it is true, then I would say yes.
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?
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
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
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 />")
I want to add a forward slash to one of my db seeds. Here is how I'm trying it:
Template.create! code: '<div style="background-image: url("/assets/forest-trees-hiker-hiking.jpg");></div>'
This results in spaces instead of slashes though...
style="background-image: url(" assets forest-trees-hiker-hiking.jpg");
It looks like you're very close with the suggestions noted in the comments, but you're missing one closing quotation mark after the semicolon:
"<div style='background-image: url(\"/assets/forest-trees-hiker-hiking.jpg\");'></div>"
Note that the entire div is wrapped in double quotes, and the style is wrapped in single quotes, which can be nested without confusion. But since you need to nest another string within those strings, you must escape the quotes around the url, in order to tell the program that you are not closing one of your existing quotation marks.
As #usmanali wrote, you have to use backslash escape sign \
This should works for you: Template.create! code: '<div style="background-image: url("\/assets\/forest-trees-hiker-hiking.jpg");></div>'
More reading: http://en.wikibooks.org/wiki/Ruby_Programming/Strings#Single_quotes
I need to embed links in my translated texts. I followed this post, but it doesn't seem to work in rails 3 anymore as the html tags don't get rendered properly.
Anyone knows how to get this done in rails 3?
Update:
Apparently, the html tags can be escaped by using the html_safe method. But does anyone know if there's another way to solve this problem without using html_safe?
I would like to avoid unescaping my html tags if possible, b/c I've encountered a situation where I have to pass in a text field into my translation, and I would like to avoid unescaping any strings that are user inputted.
Change {{url}} to %{url} and you should be good to go.
Update
Ok, thanks, that's important information about what "doesn't work" means :) So, you need to call the html_safe method on your call to link_to, eg.
link_to(t("log_in_href"), login_path).html_safe
This will tell Rails to render the HTML, not escaped.
Whenever I use Html.ActionLink it always Html encodes my display string. For instance I want my link to look like this:
More…
it outputs like this: More…
&hellip is "..." incase you were wondering.
However the actionlink outputs the actual text "…" as the link text. I have the same problem with if I want to output this:
<em>My-Post-Title-Here</em>
I wind up with:
<em>My-Post-Title-Here</em>
Any idea how to do this?
It looks like ActionLink always uses calls HttpUtility.Encode on the link text. You could use UrlHelper to generate the href and build the anchor tag yourself.
<a href='#Url.Action("Posts", ...)'>More…</a>
Alternatively you can "decode" the string you pass to ActionLink. Constructing the link in HTML seems to be slightly more readable (to me) - especially in Razor. Below is the equivalent for comparison.
#Html.ActionLink(HttpUtility.HtmlDecode("More…"), "Posts", ...)
The answer given by Sam is actually correct and I used it in my solution so I have therefore tried it myself.
You may want to remove the extra parenthesis so it becomes something like this:
#Html.ActionLink(HttpUtility.HtmlDecode("&"), "Index", "Home")
Alternatively, just use a plain Unicode ellipsis character \u2026 and let MVC worry about how to encode it. Unless there's some particularly compelling reason you'd specifically need a hellip entity reference as opposed to a character reference or just including the character as simple UTF-8 bytes.
Alternative alternatively: just use three periods. The ellipsis (U+2026) is a compatibility character, only included to round-trip to pre-Unicode encodings. It gets you very little compared to simple dots.
Check out this:
<p>Some text #(new HtmlString(stringToPaste)) </p>
Decode it before passing the value in. Just had this same issue (different characters) and it works fine:
Eg:
#Html.ActionLink(HttpUtility.HtmlDecode(_("&")), "Index", "Home")
Annoying though