I'm trying to show the contents of a field from the database in a <p> element. In the html.erb template the code looks like:
<p><%= front.gsub(/(\r)?\n/, "<br>") %></p> ...
The issue I'm having is that to escape the breaks, I have to apply the .html_safe method at the end of the above gsub, but doing so opens the whole application to XSS attacks. How can I only allow the breaks to be escaped?
You can use the simple_formatmethod.
<%= simple_format(front) %>
More here => http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html#method-i-simple_format
This is based on the simple_format helper. We can use sanitize to remove bad tags that allow XSS attacks.
<%= sanitize(front).gsub(/(\r)?\n/, "<br/>").html_safe %>
You can also use strip_tags if you want to remove all HTML tags before replacing new lines with <br>.
<%= strip_tags(front).gsub(/(\r)?\n/, "<br/>").html_safe %>
Have you considered wrapping the text into <pre>-tags instead? That will keep the basic formatting (newlines, spaces, ...).
Related
Rails 7 / Ruby 3
I'm currently working on a site that requires code examples to be displayed on a page - I can get these to display utilising the extra % character trick, however, for some of the examples I need to have a variable within them that is resolved (e.g. like the users' own API key etc...).
Consider I have #variable = "Resolved Variable"
<%%= link_to #variable, variable_path %>
Outputs on the page explicitly as
<%= link_to #variable, variable_path %>
But I really need the #variable to resolve and show on the page as:
<%= link_to "Resolved Variable", variable_path %>
I've tried all kinds of escaping the variable, but it seems that <%%= ensures that nothing following it can be resolved.
Any ideas?
Any text you haven't html_encodeed will be displayed as plain text.
My suggestion to you is to create a interpolated string that you could use to generate your intended result. For example:
output_text = "<%= link_to '#{#variable}', variable_path %>"
And, not sure if this is what you're looking for, but you can get a good UI by adding some Javascript library to format you code in the language in intend (in this case Ruby, it seems).
In case that's interesting to you, check the Prism lib, or check how to add it to your project here
I hope this helps.
With kind regards,
Rogerio
<%% in ERB will simply output <%, no more, no less. In particular, it won't attempt to parse the code after <%% as Ruby. However, this doesn't mean that you can't have another <%= ... %> after <%%:
require 'erb'
template = <<-EOD
<%%= link_to <%= #variable.inspect %>, variable_path %>
EOD
#variable = "Resolved Variable"
puts ERB.new(template).result
The inspect method will add quotes around your string and also escape certain characters as needed.
Output:
<%= link_to "Resolved Variable", variable_path %>
I have a text_area tag which allows the user to enter his Bio. When a user is tyoing and if he hits enter or return, a new line starts. But when he saves his input all the text is displayed in one paragraph. I want functionality similar to what stack overflow has.
For example - I hit enter now
This text appears on a new line*
How can I do this?
This is my code in Rails:
<%= form_for :profile do |profile| %>
<%= profile.text_area :bio %>
<%= f.submit "Save Bio" %></p>
<% end %>
You should use text editor for example ckeditor (to simplify web content creation), and in view try simpleformat or raw:
<%= simple_format("Here is some basic text...\n...with a line break.") %>
<%= raw("Here is some basic text...<br/>...with a line break.") %>
There are many ways to handle this. When displaying text previously inputed in text area you can:
replace newline characters with <br/> tags
use <pre> tag and display text inside that tag
split text by newline characters and then wrap each of the chunks into <p> tags
When using approach 1 or 3, make sure to pass text through raw helper, so that any tags within text are displayed. Be aware though, that user may pass arbitrary html inside the textarea, hence your code may be subject to xss attacks.
i replaced line feed characters with HTML line break as
#post.description.gsub(/\n/, "<br/>")
I am trying to show the output within tags. But I see as follows:
Used, like new book<br/>New book costs $150<br/>Awesome book!
Need help. Thanks.
Use simple_format for this as it will automatically convert new lines into breaks.
<%= simple_format(#post.description) %>
I need to display user comments, omitting HTML to prevent attacks (when custom styled elements can be posted as comments)
The only thing, i would like to keep by displaying - is tag
I displaying the comment in this way:
<p class="content"><%=h comment.content.gsub(/\n/,"<br/>") %></p>
Comment is suppossed to be saved in database without any markup
Line ending are converted to "br" tags
But, sure, they are gone, because of =h output mode.
Is there a way to kill all html, except "br" tags ?
You could either use sanitize which keeps only specified HTML tags:
<%= sanitize comment.content.gsub(/\n/,"<br/>"), :tags => ['br'] %>
or (in your case preferably) change the order of both and do the html_escape yourself:
<%= html_escape(comment.content).gsub(/\n/,"<br/>") %>
I'd recommend to use white_list plugin. It's safety for XSS attacts and you will be able to control list of allowed tags
In the controller, I have an variable #xml_string = "<tag> hello \n world </tag>". Now I want to show the content of #xml_string. In erb file I wrote <%= #xml_string %>, but this can only display hello world, the xml tag <tag> </tag> was missed and \n was ignored.
Aslo , <% render :text => #xml_string , :content_type = 'application/xml' %> would not show any thing at all.
what is the correct way to achieve this? Thanks.
HTML ignores new line characters and white spaces unless you wrap the content into a tag that is whitespace-aware.
<pre><%=h #xml_string %></pre>
Otherwise, replace the "\n" with a line break. In this case you need to manually escape the HTML string.
<%=h #xml_string.gsub("<", "<").gsub("\n", "<br>") %>
try:
<%=h #xml_string %>
You could use this:
<%=h #xml_string.dump[1..-2] %>
The dump method will simply return the string in a way that makes str == eval(str.dump). That means it includes the quotes, so you need the [1..-2] to slice those away.