Commit 8df1c088a12e350ccf8cf263ab2543128fc3cd9f

Authored by Braulio Bhavamitra
2 parents 05c93013 9172bf4b

Merge branch 'new_security' into 'master'

Fixing html_safe for noosfero

This MR treats of Noosfero's safe strings (with html_safe), because at the moment Noosfero treats all strings as safe, which allows users to inject malicious code.

See merge request !859
Showing 115 changed files with 351 additions and 301 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 115 files displayed.

app/controllers/my_profile/cms_controller.rb
... ... @@ -108,7 +108,7 @@ class CmsController < MyProfileController
108 108 end
109 109  
110 110 def new
111   - # FIXME this method should share some logic wirh edit !!!
  111 + # FIXME this method should share some logic with edit !!!
112 112  
113 113 @success_back_to = params[:success_back_to]
114 114 # user must choose an article type first
... ... @@ -365,7 +365,7 @@ class CmsController < MyProfileController
365 365 def search
366 366 query = params[:q]
367 367 results = find_by_contents(:uploaded_files, profile, profile.files.published, query)[:results]
368   - render :text => article_list_to_json(results), :content_type => 'application/json'
  368 + render :text => article_list_to_json(results).html_safe, :content_type => 'application/json'
369 369 end
370 370  
371 371 def search_article_privacy_exceptions
... ...
app/controllers/my_profile/profile_editor_controller.rb
... ... @@ -29,6 +29,7 @@ class ProfileEditorController < MyProfileController
29 29 Image.transaction do
30 30 begin
31 31 @plugins.dispatch(:profile_editor_transaction_extras)
  32 + # TODO: This is unsafe! Add sanitizer
32 33 @profile_data.update!(params[:profile_data])
33 34 redirect_to :action => 'index', :profile => profile.identifier
34 35 rescue Exception => ex
... ...
app/helpers/action_tracker_helper.rb
... ... @@ -5,22 +5,22 @@ module ActionTrackerHelper
5 5 end
6 6  
7 7 def new_friendship_description ta
8   - n_('has made 1 new friend:<br />%{name}', 'has made %{num} new friends:<br />%{name}', ta.get_friend_name.size) % {
  8 + n_('has made 1 new friend:<br />%{name}', 'has made %{num} new friends:<br />%{name}', ta.get_friend_name.size).html_safe % {
9 9 num: ta.get_friend_name.size,
10   - name: ta.collect_group_with_index(:friend_name) do |n,i|
  10 + name: safe_join(ta.collect_group_with_index(:friend_name) do |n,i|
11 11 link_to image_tag(ta.get_friend_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/person-icon.png")),
12 12 ta.get_friend_url[i], title: n
13   - end.join
  13 + end)
14 14 }
15 15 end
16 16  
17 17 def join_community_description ta
18   - n_('has joined 1 community:<br />%{name}', 'has joined %{num} communities:<br />%{name}', ta.get_resource_name.size) % {
  18 + n_('has joined 1 community:<br />%{name}'.html_safe, 'has joined %{num} communities:<br />%{name}'.html_safe, ta.get_resource_name.size) % {
19 19 num: ta.get_resource_name.size,
20 20 name: ta.collect_group_with_index(:resource_name) do |n,i|
21   - link_to image_tag(ta.get_resource_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/community-icon.png")),
  21 + link = link_to image_tag(ta.get_resource_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/community-icon.png")),
22 22 ta.get_resource_url[i], title: n
23   - end.join
  23 + end.join.html_safe
24 24 }
25 25 end
26 26  
... ...
app/helpers/application_helper.rb
... ... @@ -99,7 +99,6 @@ module ApplicationHelper
99 99 #
100 100 # TODO: implement correcly the 'Help' button click
101 101 def help(content = nil, link_name = nil, options = {}, &block)
102   -
103 102 link_name ||= _('Help')
104 103  
105 104 @help_message_id ||= 1
... ... @@ -122,7 +121,7 @@ module ApplicationHelper
122 121 button = link_to_function(content_tag('span', link_name), "Element.show('#{help_id}')", options )
123 122 close_button = content_tag("div", link_to_function(_("Close"), "Element.hide('#{help_id}')", :class => 'close_help_button'))
124 123  
125   - text = content_tag('div', button + content_tag('div', content_tag('div', content) + close_button, :class => 'help_message', :id => help_id, :style => 'display: none;'), :class => 'help_box')
  124 + text = content_tag('div', button + content_tag('div', content_tag('div', content.html_safe) + close_button, :class => 'help_message', :id => help_id, :style => 'display: none;'), :class => 'help_box')
126 125  
127 126 unless block.nil?
128 127 concat(text)
... ... @@ -362,8 +361,8 @@ module ApplicationHelper
362 361 def popover_menu(title,menu_title,links,html_options={})
363 362 html_options[:class] = "" unless html_options[:class]
364 363 html_options[:class] << " menu-submenu-trigger"
365   - html_options[:onclick] = "toggleSubmenu(this, '#{menu_title}', #{CGI::escapeHTML(links.to_json)}); return false"
366 364  
  365 + html_options[:onclick] = "toggleSubmenu(this, '#{menu_title}', #{CGI::escapeHTML(links.to_json)}); return false".html_safe
367 366 link_to(content_tag(:span, title), '#', html_options)
368 367 end
369 368  
... ... @@ -473,9 +472,9 @@ module ApplicationHelper
473 472 map(&:role)
474 473 names = []
475 474 roles.each do |role|
476   - names << content_tag('span', role.name, :style => "color: #{role_color(role, resource.environment.id)}")
  475 + names << content_tag('span', role.name, :style => "color: #{role_color(role, resource.environment.id)}").html_safe
477 476 end
478   - names.join(', ')
  477 + safe_join(names, ', ')
479 478 end
480 479  
481 480 def role_color(role, env_id)
... ... @@ -911,7 +910,8 @@ module ApplicationHelper
911 910 end
912 911  
913 912 def admin_link
914   - user.is_admin?(environment) ? link_to('<i class="icon-menu-admin"></i><strong>' + _('Administration') + '</strong>', environment.admin_url, :title => _("Configure the environment"), :class => 'admin-link') : ''
  913 + admin_icon = '<i class="icon-menu-admin"></i><strong>' + _('Administration') + '</strong>'
  914 + user.is_admin?(environment) ? link_to(admin_icon.html_safe, environment.admin_url, :title => _("Configure the environment"), :class => 'admin-link') : ''
915 915 end
916 916  
917 917 def usermenu_logged_in
... ... @@ -920,23 +920,39 @@ module ApplicationHelper
920 920 if count > 0
921 921 pending_tasks_count = link_to(count.to_s, user.tasks_url, :id => 'pending-tasks-count', :title => _("Manage your pending tasks"))
922 922 end
  923 + user_identifier = "<i style='background-image:url(#{user.profile_custom_icon(gravatar_default)})'></i><strong>#{user.identifier}</strong>"
  924 + welcome_link = link_to(user_identifier.html_safe, user.public_profile_url, :id => "homepage-link", :title => _('Go to your homepage'))
  925 + welcome_span = _("<span class='welcome'>Welcome,</span> %s") % welcome_link.html_safe
  926 + ctrl_panel_icon = '<i class="icon-menu-ctrl-panel"></i>'
  927 + ctrl_panel_section = '<strong>' + ctrl_panel_icon + _('Control panel') + '</strong>'
  928 + ctrl_panel_link = link_to(ctrl_panel_section.html_safe, user.admin_url, :class => 'ctrl-panel', :title => _("Configure your personal account and content"))
  929 + logout_icon = '<i class="icon-menu-logout"></i><strong>' + _('Logout') + '</strong>'
  930 + logout_link = link_to(logout_icon.html_safe, { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system"))
  931 + join_result = safe_join(
  932 + [welcome_span.html_safe, render_environment_features(:usermenu).html_safe, admin_link.html_safe,
  933 + manage_enterprises.html_safe, manage_communities.html_safe, ctrl_panel_link.html_safe,
  934 + pending_tasks_count.html_safe, logout_link.html_safe], "")
  935 + join_result
  936 + end
923 937  
924   - (_("<span class='welcome'>Welcome,</span> %s") % link_to("<i style='background-image:url(#{user.profile_custom_icon(gravatar_default)})'></i><strong>#{user.identifier}</strong>", user.url, :id => "homepage-link", :title => _('Go to your homepage'))) +
925   - render_environment_features(:usermenu) +
926   - admin_link +
927   - manage_enterprises +
928   - manage_communities +
929   - link_to('<i class="icon-menu-ctrl-panel"></i><strong>' + _('Control panel') + '</strong>', user.admin_url, :class => 'ctrl-panel', :title => _("Configure your personal account and content")) +
930   - pending_tasks_count +
931   - link_to('<i class="icon-menu-logout"></i><strong>' + _('Logout') + '</strong>', { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system"))
  938 + def usermenu_notlogged_in
  939 + login_str = '<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>'
  940 + ret = _("<span class='login'>%s</span>") % modal_inline_link_to(login_str.html_safe, login_url, '#inlineLoginBox', :id => 'link_login')
  941 + return ret.html_safe
932 942 end
933 943  
  944 + def usermenu_signup
  945 + signup_str = '<strong>' + _('Sign up') + '</strong>'
  946 + ret = _("<span class='or'>or</span> <span class='signup'>%s</span>") % link_to(signup_str.html_safe, :controller => 'account', :action => 'signup')
  947 + return ret.html_safe
  948 +
  949 + end
934 950 def limited_text_area(object_name, method, limit, text_area_id, options = {})
935   - content_tag(:div, [
  951 + content_tag(:div, safe_join([
936 952 text_area(object_name, method, { :id => text_area_id, :onkeyup => "limited_text_area('#{text_area_id}', #{limit})" }.merge(options)),
937 953 content_tag(:p, content_tag(:span, limit) + ' ' + _(' characters left'), :id => text_area_id + '_left'),
938 954 content_tag(:p, _('Limit of characters reached'), :id => text_area_id + '_limit', :style => 'display: none')
939   - ].join, :class => 'limited-text-area')
  955 + ]), :class => 'limited-text-area')
940 956 end
941 957  
942 958 def expandable_text_area(object_name, method, text_area_id, options = {})
... ... @@ -1032,8 +1048,8 @@ module ApplicationHelper
1032 1048 end
1033 1049  
1034 1050 def render_tabs(tabs)
1035   - titles = tabs.inject(''){ |result, tab| result << content_tag(:li, link_to(tab[:title], '#'+tab[:id]), :class => 'tab') }
1036   - contents = tabs.inject(''){ |result, tab| result << content_tag(:div, tab[:content], :id => tab[:id]) }
  1051 + titles = tabs.inject(''.html_safe){ |result, tab| result << content_tag(:li, link_to(tab[:title], '#'+tab[:id]), :class => 'tab') }
  1052 + contents = tabs.inject(''.html_safe){ |result, tab| result << content_tag(:div, tab[:content], :id => tab[:id]) }
1037 1053  
1038 1054 content_tag(:div, content_tag(:ul, titles) + raw(contents), :class => 'ui-tabs')
1039 1055 end
... ... @@ -1051,7 +1067,7 @@ module ApplicationHelper
1051 1067 def expirable_link_to(expired, content, url, options = {})
1052 1068 if expired
1053 1069 options[:class] = (options[:class] || '') + ' disabled'
1054   - content_tag('a', '&nbsp;'+content_tag('span', content), options)
  1070 + content_tag('a', '&nbsp;'.html_safe+content_tag('span', content), options)
1055 1071 else
1056 1072 if options[:modal]
1057 1073 options.delete(:modal)
... ... @@ -1084,7 +1100,7 @@ module ApplicationHelper
1084 1100  
1085 1101 radios = templates.map do |template|
1086 1102 content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, environment.is_default_template?(template)))
1087   - end.join("\n")
  1103 + end.join("\n").html_safe
1088 1104  
1089 1105 content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') +
1090 1106 content_tag('p', _('Your profile will be created according to the selected template. Click on the options to view them.'), :style => 'margin: 5px 15px;padding: 0px 10px;') +
... ... @@ -1124,7 +1140,7 @@ module ApplicationHelper
1124 1140 content_tag(:div, :class => 'errorExplanation', :id => 'errorExplanation') do
1125 1141 content_tag(:h2, _('Errors while saving')) +
1126 1142 content_tag(:ul) do
1127   - errors.map { |err| content_tag(:li, err) }.join
  1143 + safe_join(errors.map { |err| content_tag(:li, err) })
1128 1144 end
1129 1145 end
1130 1146 end
... ... @@ -1234,6 +1250,7 @@ module ApplicationHelper
1234 1250 :href=>"#",
1235 1251 :title=>_("Exit full screen mode")
1236 1252 })
  1253 + content.html_safe
1237 1254 end
1238 1255  
1239 1256 end
... ...
app/helpers/block_helper.rb
... ... @@ -3,13 +3,13 @@ module BlockHelper
3 3 def block_title(title, subtitle=nil)
4 4 block_header = block_heading title
5 5 block_header += block_heading(subtitle, 'h4') if subtitle
6   - content_tag 'div', block_header, :class => 'block-header'
  6 + content_tag('div', block_header, :class => 'block-header').html_safe
7 7 end
8 8  
9 9 def block_heading(title, heading='h3')
10 10 tag_class = 'block-' + (heading == 'h3' ? 'title' : 'subtitle')
11 11 tag_class += ' empty' if title.empty?
12   - content_tag heading, content_tag('span', h(title)), :class => tag_class
  12 + content_tag heading, content_tag('span', h(title)), :class => tag_class.html_safe
13 13 end
14 14  
15 15 def highlights_block_config_image_fields(block, image={}, row_number=nil)
... ...
app/helpers/blog_helper.rb
... ... @@ -41,12 +41,12 @@ module BlogHelper
41 41 css_add << position
42 42 content << (content_tag 'div', id: "post-#{art.id}", class: css_add do
43 43 content_tag 'div', class: position + '-inner blog-post-inner' do
44   - display_post(art, conf[:format]).html_safe +
45   - '<br style="clear:both"/>'.html_safe
  44 + display_post(art, conf[:format]) +
  45 + '<br style="clear:both"/>'
46 46 end
47   - end)
  47 + end).html_safe
48 48 }
49   - content.join("\n<hr class='sep-posts'/>\n") + (pagination or '')
  49 + safe_join(content, "\n<hr class='sep-posts'/>\n") + (pagination or '').html_safe
50 50 end
51 51  
52 52 def display_post(article, format = 'full')
... ... @@ -61,7 +61,8 @@ module BlogHelper
61 61 else
62 62 '<div class="post-pic" style="background-image:url('+img+')"></div>'
63 63 end
64   - end.to_s + title + html
  64 + end.to_s.html_safe +
  65 + title.html_safe + html
65 66 end
66 67  
67 68 def display_compact_format(article)
... ...
app/helpers/box_organizer_helper.rb
... ... @@ -38,7 +38,7 @@ module BoxOrganizerHelper
38 38 content_tag(:ul,
39 39 images_path.map do |preview|
40 40 content_tag(:li, image_tag(preview, height: '240', alt: ''))
41   - end.join("\n")
  41 + end.join("\n").html_safe
42 42 )
43 43 end
44 44  
... ...
app/helpers/boxes_helper.rb
... ... @@ -44,7 +44,7 @@ module BoxesHelper
44 44  
45 45 def display_boxes(holder, main_content)
46 46 boxes = holder.boxes.with_position.first(boxes_limit(holder))
47   - content = boxes.reverse.map { |item| display_box(item, main_content) }.join("\n")
  47 + content = safe_join(boxes.reverse.map { |item| display_box(item, main_content) }, "\n")
48 48 content = main_content if (content.blank?)
49 49  
50 50 content_tag('div', content, :class => 'boxes', :id => 'boxes' )
... ... @@ -54,7 +54,7 @@ module BoxesHelper
54 54 if holder.respond_to?(element)
55 55 content_tag('div', holder.send(element), options)
56 56 else
57   - ''
  57 + ''.html_safe
58 58 end
59 59 end
60 60  
... ... @@ -70,9 +70,10 @@ module BoxesHelper
70 70  
71 71 def display_box_content(box, main_content)
72 72 context = { :article => @page, :request_path => request.path, :locale => locale, :params => request.params, :user => user, :controller => controller }
73   - box_decorator.select_blocks(box, box.blocks.includes(:box), context).map do |item|
  73 + blocks = box_decorator.select_blocks(box, box.blocks.includes(:box), context).map do |item|
74 74 display_block item, main_content
75   - end.join("\n") + box_decorator.block_target(box)
  75 + end
  76 + safe_join(blocks, "\n") + box_decorator.block_target(box)
76 77 end
77 78  
78 79 def select_blocks box, arr, context
... ... @@ -136,17 +137,18 @@ module BoxesHelper
136 137  
137 138 result = filter_html(result, block)
138 139  
139   - content_tag('div',
140   - box_decorator.block_target(block.box, block) +
141   - content_tag('div',
142   - content_tag('div',
143   - content_tag('div',
144   - result + footer_content + box_decorator.block_edit_buttons(block),
145   - :class => 'block-inner-2'),
146   - :class => 'block-inner-1'),
147   - options),
148   - :class => 'block-outer') +
149   - box_decorator.block_handle(block)
  140 + join_result = safe_join([result, footer_content, box_decorator.block_edit_buttons(block)])
  141 + content_tag_inner_1 = content_tag('div', join_result, :class => 'block-inner-2')
  142 +
  143 + content_tag_inner_2 = content_tag('div', content_tag_inner_1, :class => 'block-inner-1')
  144 + content_tag_inner_3 = content_tag('div', content_tag_inner_2, options)
  145 + content_tag_inner_4 = box_decorator.block_target(block.box, block) + content_tag_inner_3
  146 + c = content_tag('div', content_tag_inner_4, :class => 'block-outer')
  147 + box_decorator_result = box_decorator.block_handle(block)
  148 + result_final = safe_join([c, box_decorator_result], "")
  149 +
  150 +
  151 + return result_final
150 152 end
151 153  
152 154 def wrap_main_content(content)
... ... @@ -156,17 +158,17 @@ module BoxesHelper
156 158 def extract_block_content(content)
157 159 case content
158 160 when Hash
159   - content_tag('iframe', '', :src => url_for(content))
  161 + content_tag('iframe', ''.html_safe, :src => url_for(content))
160 162 when String
161 163 if content.split("\n").size == 1 and content =~ /^https?:\/\//
162   - content_tag('iframe', '', :src => content)
  164 + content_tag('iframe', ''.html_safe, :src => content)
163 165 else
164 166 content
165 167 end
166 168 when Proc
167 169 self.instance_eval(&content)
168 170 when NilClass
169   - ''
  171 + ''.html_safe
170 172 else
171 173 raise "Unsupported content for block (#{content.class})"
172 174 end
... ... @@ -175,14 +177,14 @@ module BoxesHelper
175 177 module DontMoveBlocks
176 178 # does nothing
177 179 def self.block_target(box, block = nil)
178   - ''
  180 + ''.html_safe
179 181 end
180 182 # does nothing
181 183 def self.block_handle(block)
182   - ''
  184 + ''.html_safe
183 185 end
184 186 def self.block_edit_buttons(block)
185   - ''
  187 + ''.html_safe
186 188 end
187 189 def self.select_blocks box, arr, context
188 190 arr = arr.select{ |block| block.visible? context }
... ... @@ -229,9 +231,9 @@ module BoxesHelper
229 231 # makes the given block draggable so it can be moved away.
230 232 def block_handle(block)
231 233 return "" unless movable?(block)
232   - icon = "<div><div>#{display_icon(block.class)}</div><span>#{_(block.class.pretty_name)}</span></div>"
  234 + icon = "<div><div>#{display_icon(block.class)}</div><span>#{_(block.class.pretty_name)}</span></div>".html_safe
233 235 block_draggable("block-#{block.id}",
234   - :helper => "function() {return cloneDraggableBlock($(this), '#{icon}')}")
  236 + :helper => "function() {return cloneDraggableBlock($(this), '#{icon}')}".html_safe)
235 237 end
236 238  
237 239 def block_draggable(element_id, options={})
... ... @@ -302,7 +304,7 @@ module BoxesHelper
302 304 buttons << modal_inline_icon(:embed, _('Embed code'), {}, "#embed-code-box-#{block.id}") << html
303 305 end
304 306  
305   - content_tag('div', buttons.join("\n") + tag('br', :style => 'clear: left'), :class => 'button-bar')
  307 + content_tag('div', buttons.join("\n").html_safe + tag('br', :style => 'clear: left'), :class => 'button-bar')
306 308 end
307 309  
308 310 def current_blocks
... ...
app/helpers/buttons_helper.rb
... ... @@ -15,9 +15,9 @@ module ButtonsHelper
15 15 end
16 16 the_title = html_options[:title] || label
17 17 if html_options[:disabled]
18   - content_tag('a', '&nbsp;'+content_tag('span', label), html_options.merge(:class => the_class, :title => the_title))
  18 + content_tag('a', '&nbsp;'.html_safe+content_tag('span', label), html_options.merge(:class => the_class, :title => the_title))
19 19 else
20   - link_to('&nbsp;'+content_tag('span', label), url, html_options.merge(:class => the_class, :title => the_title))
  20 + link_to('&nbsp;'.html_safe+content_tag('span', label), url, html_options.merge(:class => the_class, :title => the_title))
21 21 end
22 22 end
23 23  
... ...
app/helpers/catalog_helper.rb
... ... @@ -19,18 +19,18 @@ module CatalogHelper
19 19 ancestors = category.ancestors.map { |c| link_to(c.name, {:controller => :catalog, :action => 'index', :level => c.id}) }.reverse
20 20 current_level = content_tag('strong', category.name)
21 21 all_items = [start] + ancestors + [current_level]
22   - content_tag('div', all_items.join(' &rarr; '), :id => 'breadcrumb')
  22 + content_tag('div', safe_join(all_items, ' &rarr; '), :id => 'breadcrumb')
23 23 end
24 24  
25 25 def category_link(category)
26 26 count = profile.products.from_category(category).count
27 27 name = truncate(category.name, :length => 22 - count.to_s.size)
28 28 link = link_to(name, {:controller => 'catalog', :action => 'index', :level => category.id}, :title => category.name)
29   - content_tag('div', "#{link} <span class=\"count\">#{count}</span>") if count > 0
  29 + content_tag('div', "#{link} <span class=\"count\">#{count}</span>".html_safe) if count > 0
30 30 end
31 31  
32 32 def category_with_sub_list(category)
33   - content_tag 'li', "#{category_link(category)}\n#{sub_category_list(category)}"
  33 + content_tag 'li', "#{category_link(category)}\n#{sub_category_list(category)}".html_safe
34 34 end
35 35  
36 36 def sub_category_list(category)
... ... @@ -39,7 +39,7 @@ module CatalogHelper
39 39 cat_link = category_link sub_category
40 40 sub_categories << content_tag('li', cat_link) unless cat_link.nil?
41 41 end
42   - content_tag('ul', sub_categories.join) if sub_categories.size > 0
  42 + content_tag('ul', sub_categories.join.html_safe) if sub_categories.size > 0
43 43 end
44 44  
45 45 end
... ...
app/helpers/content_viewer_helper.rb
... ... @@ -7,7 +7,8 @@ module ContentViewerHelper
7 7 def display_number_of_comments(n)
8 8 base_str = "<span class='comment-count hide'>#{n}</span>"
9 9 amount_str = n == 0 ? _('no comments yet') : (n == 1 ? _('One comment') : _('%s comments') % n)
10   - base_str + "<span class='comment-count-write-out'>#{amount_str}</span>"
  10 + base_str += "<span class='comment-count-write-out'>#{amount_str}</span>"
  11 + base_str.html_safe
11 12 end
12 13  
13 14 def number_of_comments(article)
... ... @@ -19,11 +20,11 @@ module ContentViewerHelper
19 20 title = content_tag('h1', h(title), :class => 'title')
20 21 if article.belongs_to_blog? || article.belongs_to_forum?
21 22 unless args[:no_link]
22   - title = content_tag('h1', link_to(article.name, article.url), :class => 'title')
  23 + title = content_tag('h1', link_to(article.name, url_for(article.url)), :class => 'title')
23 24 end
24 25 comments = ''
25 26 unless args[:no_comments] || !article.accept_comments
26   - comments = (" - %s") % link_to_comments(article)
  27 + comments = (" - %s").html_safe % link_to_comments(article)
27 28 end
28 29 date_format = show_with_right_format_date article
29 30 title << content_tag('span',
... ...
app/helpers/display_helper.rb
... ... @@ -53,18 +53,19 @@ module DisplayHelper
53 53 end
54 54  
55 55 def txt2html(txt)
56   - txt.strip.
  56 + ret = txt.strip.
57 57 gsub( /\s*\n\s*\n\s*/, "\r<p/>\r" ).
58 58 gsub( /\s*\n\s*/, "\n<br/>\n" ).
59 59 gsub( /\r/, "\n" ).
60 60 gsub( /(^|\s)(www\.[^\s]+|https?:\/\/[^\s]+)/ ) do
61 61 pre_char, href = $1, $2
62 62 href = 'http://'+href if ! href.match /^https?:/
63   - content = href.gsub(/^https?:\/\//, '').scan(/.{1,4}/).join('&#x200B;')
  63 + content = safe_join(href.gsub(/^https?:\/\//, '').scan(/.{1,4}/), '&#x200B;'.html_safe)
64 64 pre_char +
65 65 content_tag(:a, content, :href => href, :target => '_blank',
66   - :rel => 'nofolow', :onclick => "return confirm('%s')" %
  66 + :rel => 'nofolow', :onclick => "return confirm('%s')".html_safe %
67 67 _('Are you sure you want to visit this web site?'))
68 68 end
  69 + ret.html_safe
69 70 end
70 71 end
... ...
app/helpers/events_helper.rb
1 1 module EventsHelper
2 2  
3 3 include DatesHelper
  4 + include ActionView::Helpers::OutputSafetyHelper
  5 +
4 6 def list_events(date, events)
5 7 title = _('Events for %s') % show_date_month(date)
  8 + user_events = events.select { |item| item.display_to?(user) }
  9 + events_for_month = safe_join(user_events.map {|item| display_event_in_listing(item)}, '')
6 10 content_tag('h2', title) +
7 11 content_tag('div',
8 12 (events.any? ?
9   - content_tag('table', events.select { |item| item.display_to?(user) }.map {|item| display_event_in_listing(item)}.join('')) :
10   - content_tag('em', _('No events for this month'), :class => 'no-events')
  13 + content_tag('table', events_for_month) :
  14 + content_tag('em', _('No events for this month'), :class => 'no-events')
11 15 ), :id => 'agenda-items'
12 16 )
13 17 end
... ...
app/helpers/forms_helper.rb
... ... @@ -101,7 +101,7 @@ module FormsHelper
101 101  
102 102 def required_fields_message
103 103 content_tag('p', content_tag('span',
104   - _("The <label class='pseudoformlabel'>highlighted</label> fields are mandatory."),
  104 + _("The <label class='pseudoformlabel'>highlighted</label> fields are mandatory.").html_safe,
105 105 :class => 'required-field'
106 106 ))
107 107 end
... ... @@ -112,10 +112,11 @@ module FormsHelper
112 112 options_for_select = container.inject([]) do |options, element|
113 113 text, value = option_text_and_value(element)
114 114 selected_attribute = ' selected="selected"' if option_value_selected?(value, selected)
115   - options << %(<option title="#{html_escape(text.to_s)}" value="#{html_escape(value.to_s)}"#{selected_attribute}>#{html_escape(text.to_s)}</option>)
  115 + opt = %(<option title="#{html_escape(text.to_s)}" value="#{html_escape(value.to_s)}"#{selected_attribute}>#{html_escape(text.to_s)}</option>)
  116 + options << opt.html_safe
116 117 end
117 118  
118   - options_for_select.join("\n")
  119 + safe_join(options_for_select, "\n")
119 120 end
120 121  
121 122 def balanced_table(items, per_row=3)
... ... @@ -248,8 +249,8 @@ module FormsHelper
248 249 def date_range_field(from_name, to_name, from_value, to_value, datepicker_options = {}, html_options = {})
249 250 from_id = html_options[:from_id] || 'datepicker-from-date'
250 251 to_id = html_options[:to_id] || 'datepicker-to-date'
251   - return _('From') +' '+ date_field(from_name, from_value, datepicker_options, html_options.merge({:id => from_id})) +
252   - ' ' + _('until') +' '+ date_field(to_name, to_value, datepicker_options, html_options.merge({:id => to_id}))
  252 + return (_('From') +' '+ date_field(from_name, from_value, datepicker_options, html_options.merge({:id => from_id})) +
  253 + ' ' + _('until') +' '+ date_field(to_name, to_value, datepicker_options, html_options.merge({:id => to_id}))).html_safe
253 254 end
254 255  
255 256 def select_folder(label_text, field_id, collection, default_value=nil, html_options = {}, js_options = {})
... ...
app/helpers/forum_helper.rb
... ... @@ -35,7 +35,7 @@ module ForumHelper
35 35 :id => "post-#{art.id}"
36 36 )
37 37 }
38   - content_tag('table', content.join) + (pagination or '')
  38 + content_tag('table', safe_join(content, "")) + (pagination or '').html_safe
39 39 end
40 40  
41 41 def last_topic_update(article)
... ...
app/helpers/language_helper.rb
... ... @@ -40,7 +40,7 @@ module LanguageHelper
40 40 else
41 41 link_to(name, params.merge(:lang => code), :rel => 'nofollow')
42 42 end
43   - end.join(separator)
  43 + end.join(separator).html_safe
44 44 content_tag('div', languages, :id => 'language-chooser', :help => _('The language you choose here is the language used for options, buttons, etc. It does not affect the language of the content created by other users.'))
45 45 end
46 46 end
... ...
app/helpers/layout_helper.rb
... ... @@ -40,7 +40,8 @@ module LayoutHelper
40 40  
41 41 output += templete_javascript_ng.to_s
42 42  
43   - output
  43 + # This output should be safe!
  44 + output.html_safe
44 45 end
45 46  
46 47 def noosfero_stylesheets
... ... @@ -64,7 +65,9 @@ module LayoutHelper
64 65 output << stylesheet_link_tag(global_css_pub)
65 66 end
66 67 output << stylesheet_link_tag(theme_stylesheet_path)
67   - output.join "\n"
  68 +
  69 + # This output should be safe!
  70 + output.join("\n").html_safe
68 71 end
69 72  
70 73 def noosfero_layout_features
... ...
app/helpers/manage_products_helper.rb
... ... @@ -38,10 +38,11 @@ module ManageProductsHelper
38 38 end
39 39  
40 40 def options_for_select_categories(categories, selected = nil)
41   - categories.sort_by{|cat| cat.name.transliterate}.map do |category|
42   - selected_attribute = selected.nil? ? '' : (category == selected ? "selected='selected'" : '')
43   - "<option value='#{category.id}' title='#{category.name}' #{selected_attribute}>#{category.name + (category.leaf? ? '': ' &raquo;')}</option>"
44   - end.join("\n")
  41 + safe_join(categories.sort_by{ |cat|
  42 + cat.name.transliterate}.map do |category|
  43 + selected_attribute = selected.nil? ? '' : (category == selected ? "selected='selected'" : '')
  44 + "<option value='#{category.id}' title='#{category.name}' #{selected_attribute}>#{category.name + (category.leaf? ? '': ' &raquo;')}</option>".html_safe
  45 + end, "\n")
45 46 end
46 47  
47 48 def build_selects_for_ancestors(ancestors, current_category)
... ... @@ -76,10 +77,13 @@ module ManageProductsHelper
76 77  
77 78 def categories_container(categories_selection_html, hierarchy_html = '')
78 79 content_tag 'div',
79   - render('categories_autocomplete') +
80   - hidden_field_tag('selected_category_id') +
81   - content_tag('div', hierarchy_html, :id => 'hierarchy_navigation') +
82   - content_tag('div', categories_selection_html, :id => 'categories_container_wrapper'),
  80 + safe_join(
  81 + [
  82 + render('categories_autocomplete'),
  83 + hidden_field_tag('selected_category_id'),
  84 + content_tag('div', hierarchy_html, :id => 'hierarchy_navigation'),
  85 + content_tag('div', categories_selection_html, :id => 'categories_container_wrapper')
  86 + ], ''),
83 87 :id => 'categories-container'
84 88 end
85 89  
... ...
app/helpers/profile_editor_helper.rb
... ... @@ -129,7 +129,11 @@ module ProfileEditorHelper
129 129 else
130 130 domains = environment.domains
131 131 end
132   - labelled_form_field(_('Preferred domain name:'), select(object, :preferred_domain_id, domains.map {|item| [item.name, item.id]}, :prompt => '&lt;' + _('Select domain') + '&gt;'))
  132 + select_domain_prompt = '&lt;'.html_safe + _('Select domain').html_safe + '&gt;'.html_safe
  133 + select_field = select(object, :preferred_domain_id, domains.map {
  134 + |item| [item.name, item.id]}, :prompt => select_domain_prompt.html_safe)
  135 +
  136 + labelled_form_field(_('Preferred domain name:'), select_field)
133 137 end
134 138  
135 139 def control_panel(&block)
... ...
app/helpers/profile_image_helper.rb
... ... @@ -131,7 +131,7 @@ module ProfileImageHelper
131 131 links = links_for_balloon(profile)
132 132 content_tag('div', content_tag(tag,
133 133 (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ?
134   - popover_menu(_('Profile links'),profile.short_name,links,{:class => trigger_class, :url => url}) : "") +
  134 + popover_menu(_('Profile links'),profile.short_name,links,{:class => trigger_class, :url => url}) : "").html_safe +
135 135 link_to(
136 136 content_tag( 'span', profile_image( profile, size ), :class => img_class ) +
137 137 content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) +
... ... @@ -139,7 +139,7 @@ module ProfileImageHelper
139 139 profile.url,
140 140 :class => 'profile_link url',
141 141 :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name,
142   - :title => profile.name ),
  142 + :title => profile.name ).html_safe,
143 143 :class => 'vcard'), :class => 'common-profile-list-block')
144 144 end
145 145 end
... ...
app/helpers/search_helper.rb
... ... @@ -124,10 +124,10 @@ module SearchHelper
124 124 def filters(asset)
125 125 return if !asset
126 126 klass = asset_class(asset)
127   - content_tag('div', klass::SEARCH_FILTERS.map do |name, options|
  127 + content_tag('div', safe_join(klass::SEARCH_FILTERS.map do |name, options|
128 128 default = klass.respond_to?("default_search_#{name}") ? klass.send("default_search_#{name}".to_s) : nil
129 129 select_filter(name, options, default)
130   - end.join("\n"), :id => 'search-filters')
  130 + end, "\n"), :id => 'search-filters')
131 131 end
132 132  
133 133 def assets_menu(selected)
... ... @@ -137,11 +137,11 @@ module SearchHelper
137 137 # menu.
138 138 assets.delete(:events)
139 139 content_tag('ul',
140   - assets.map do |asset|
  140 + safe_join(assets.map do |asset|
141 141 options = {}
142 142 options.merge!(:class => 'selected') if selected.to_s == asset.to_s
143 143 content_tag('li', asset_link(asset), options)
144   - end.join("\n"),
  144 + end, "\n"),
145 145 :id => 'assets-menu')
146 146 end
147 147  
... ...
app/helpers/tags_helper.rb
... ... @@ -58,7 +58,7 @@ module TagsHelper
58 58  
59 59 if options[:show_count]
60 60 display_count = options[:show_count] ? "<small><sup>(#{count})</sup></small>" : ""
61   - link_to tag + display_count, destination, :style => style
  61 + link_to (tag + display_count).html_safe, destination, :style => style
62 62 else
63 63 link_to h(tag) , destination, :style => style,
64 64 :title => n_( 'one item', '%d items', count ) % count
... ...
app/helpers/tinymce_helper.rb
... ... @@ -7,7 +7,7 @@ module TinymceHelper
7 7 output += javascript_include_tag 'tinymce/js/tinymce/jquery.tinymce.min.js'
8 8 output += javascript_include_tag 'tinymce.js'
9 9 output += include_macro_js_files.to_s
10   - output
  10 + output.html_safe
11 11 end
12 12  
13 13 def tinymce_init_js options = {}
... ... @@ -37,7 +37,7 @@ module TinymceHelper
37 37 #cleanup non tinymce options
38 38 options = options.except :mode
39 39  
40   - "noosfero.tinymce.init(#{options.to_json})"
  40 + "noosfero.tinymce.init(#{options.to_json})".html_safe
41 41 end
42 42  
43 43 def menubar mode
... ...
app/models/approve_article.rb
... ... @@ -86,7 +86,7 @@ class ApproveArticle &lt; Task
86 86  
87 87 def information
88 88 if article
89   - {:message => _('%{requestor} wants to publish the article: %{linked_subject}.')}
  89 + {:message => _('%{requestor} wants to publish the article: %{linked_subject}.').html_safe}
90 90 else
91 91 {:message => _("The article was removed.")}
92 92 end
... ...
app/models/create_community.rb
... ... @@ -60,9 +60,9 @@ class CreateCommunity &lt; Task
60 60  
61 61 def information
62 62 if description.blank?
63   - { :message => _('%{requestor} wants to create community %{subject} with no description.') }
  63 + { :message => _('%{requestor} wants to create community %{subject} with no description.').html_safe }
64 64 else
65   - { :message => _('%{requestor} wants to create community %{subject} with this description:<p><em>%{description}</em></p>'),
  65 + { :message => _('%{requestor} wants to create community %{subject} with this description:<p><em>%{description}</em></p>').html_safe,
66 66 :variables => {:description => description} }
67 67 end
68 68 end
... ...
app/models/create_enterprise.rb
... ... @@ -163,7 +163,7 @@ class CreateEnterprise &lt; Task
163 163 end
164 164  
165 165 def information
166   - {:message => _('%{requestor} wants to create enterprise %{subject}.')}
  166 + {:message => _('%{requestor} wants to create enterprise %{subject}.').html_safe}
167 167 end
168 168  
169 169 def reject_details
... ...
app/models/doc_item.rb
... ... @@ -17,7 +17,7 @@ class DocItem
17 17 else
18 18 match
19 19 end
20   - end
  20 + end.html_safe
21 21 end
22 22  
23 23 private
... ...
app/models/environment.rb
... ... @@ -731,7 +731,7 @@ class Environment &lt; ApplicationRecord
731 731 url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname)
732 732 url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port)
733 733 url << Noosfero.root('')
734   - url
  734 + url.html_safe
735 735 end
736 736  
737 737 def to_s
... ...
app/models/invite_friend.rb
... ... @@ -13,7 +13,7 @@ class InviteFriend &lt; Invitation
13 13 end
14 14  
15 15 def information
16   - {:message => _('%{requestor} wants to be your friend.')}
  16 + {:message => _('%{requestor} wants to be your friend.').html_safe}
17 17 end
18 18  
19 19 def accept_details
... ... @@ -25,7 +25,7 @@ class InviteFriend &lt; Invitation
25 25 end
26 26  
27 27 def target_notification_description
28   - _('%{requestor} wants to be your friend.') % {:requestor => requestor.name}
  28 + (_('%{requestor} wants to be your friend.') % {:requestor => requestor.name}).html_safe
29 29 end
30 30  
31 31 def permission
... ...
app/models/invite_member.rb
... ... @@ -25,7 +25,7 @@ class InviteMember &lt; Invitation
25 25 end
26 26  
27 27 def information
28   - {:message => _('%{requestor} invited you to join %{linked_subject}.')}
  28 + {:message => _('%{requestor} invited you to join %{linked_subject}.').html_safe}
29 29 end
30 30  
31 31 def url
... ... @@ -37,7 +37,7 @@ class InviteMember &lt; Invitation
37 37 end
38 38  
39 39 def target_notification_description
40   - _('%{requestor} invited you to join %{community}.') % {:requestor => requestor.name, :community => community.name}
  40 + (_('%{requestor} invited you to join %{community}.') % {:requestor => requestor.name, :community => community.name}).html_safe
41 41 end
42 42  
43 43 def target_notification_message
... ...
app/models/profile.rb
... ... @@ -646,7 +646,7 @@ class Profile &lt; ApplicationRecord
646 646 url << url_options[:host]
647 647 url << ':' << url_options[:port].to_s if url_options.key?(:port)
648 648 url << Noosfero.root('')
649   - url
  649 + url.html_safe
650 650 end
651 651  
652 652 private :generate_url, :url_options
... ...
app/models/suggest_article.rb
... ... @@ -65,7 +65,7 @@ class SuggestArticle &lt; Task
65 65  
66 66 def information
67 67 variables = requestor.blank? ? {:requestor => sender} : {}
68   - { :message => _('%{requestor} suggested the publication of the article: %{subject}.'),
  68 + { :message => _('%{requestor} suggested the publication of the article: %{subject}.').html_safe,
69 69 :variables => variables }
70 70 end
71 71  
... ... @@ -78,7 +78,7 @@ class SuggestArticle &lt; Task
78 78 end
79 79  
80 80 def target_notification_description
81   - _('%{requestor} suggested the publication of the article: %{article}.') %
  81 + _('%{requestor} suggested the publication of the article: %{article}.').html_safe %
82 82 {:requestor => sender, :article => article_name}
83 83 end
84 84  
... ...
app/views/account/_signup_form.html.erb
... ... @@ -107,7 +107,7 @@
107 107 <%= render :partial => 'profile_editor/person_form', :locals => {:f => f} %>
108 108 <% end %>
109 109  
110   - <%= @plugins.dispatch(:signup_extra_contents).collect { |content| instance_eval(&content) }.join("") %>
  110 + <%= safe_join(@plugins.dispatch(:signup_extra_contents).collect { |content| instance_eval(&content) }, "") %>
111 111  
112 112 <%= template_options(:people, 'profile_data') %>
113 113  
... ...
app/views/account/activate_enterprise.html.erb
... ... @@ -14,7 +14,7 @@
14 14 <div id="enterprise-activation-create-user-form" style="display: none">
15 15 <h3><%= _('Personal signup form') %></h3>
16 16 <%= render :partial => 'signup_form', :locals => { :hidden_atention => true } %>
17   - <p><%= message = _('<b>Warning</b>: this form is for your personal information, not of your enterprise. So you will have a personal account that can manage your enterprise.') %></p>
  17 + <p><%= message = _('<b>Warning</b>: this form is for your personal information, not of your enterprise. So you will have a personal account that can manage your enterprise.').html_safe %></p>
18 18 </div>
19 19  
20 20 <div id="enterprise-activation-login-form" style="display: none">
... ...
app/views/account/invalid_change_password_code.html.erb
1 1 <h1><%= _("Invalid change password code") %></h1>
2 2  
3 3 <p>
4   -<%= _('The code you are using for password change is not valid. Please try to request password change using the <a href="%s">"I forgot my password"</a> functionality.') % url_for(:action => 'forgot_password') %>
  4 +<%= _('The code you are using for password change is not valid. Please try to request password change using the <a href="%s">"I forgot my password"</a> functionality.') % url_for(:action => 'forgot_password').html_safe %>
5 5 </p>
... ...
app/views/account/login.html.erb
... ... @@ -20,7 +20,7 @@
20 20 </label>
21 21 </div>
22 22  
23   - <%= @plugins.dispatch(:login_extra_contents).collect { |content| instance_exec(&content) }.join("") %>
  23 + <%= safe_join(@plugins.dispatch(:login_extra_contents).collect { |content| instance_exec(&content) }, "") %>
24 24  
25 25 <% button_bar do %>
26 26 <%= submit_button( 'login', _('Log in') )%>
... ...
app/views/account/login_block.html.erb
... ... @@ -15,7 +15,7 @@
15 15  
16 16 <%= f.password_field :password %>
17 17  
18   - <%= @plugins.dispatch(:login_extra_contents).collect { |content| instance_eval(&content) }.join("") %>
  18 + <%= safe_join(@plugins.dispatch(:login_extra_contents).collect { |content| instance_eval(&content) }, "") %>
19 19  
20 20 <% button_bar do %>
21 21 <%= submit_button( 'login', _('Log in') )%>
... ...
app/views/account/new_password_ok.html.erb
... ... @@ -5,5 +5,5 @@
5 5 </p>
6 6  
7 7 <p>
8   -<%= _("You can <a href='%s'>login</a> now.") % url_for(:action => 'login') %>
  8 +<%= _("You can <a href='%s'>login</a> now.").html_safe % url_for(:action => 'login') %>
9 9 </p>
... ...
app/views/blocks/blog_archives.html.erb
... ... @@ -6,7 +6,7 @@
6 6 <%= content_tag('li', content_tag('strong', "#{year.to_i} (#{count})")) %>
7 7 <ul class='<%= year.to_i %>-archive'>
8 8 <% block.blog.total_number_of_posts(:by_month, year).each do |month, count| %>
9   - <%= content_tag('li', link_to("#{month_name(month.to_i)} (#{count})", block.blog.url.merge(year: year.to_i, month: month.to_i))) %>
  9 + <%= content_tag('li', link_to("#{month_name(month.to_i)} (#{count})", url_for(block.blog.url.merge(year: year.to_i, month: month.to_i)).html_safe)) %>
10 10 <% end %>
11 11 </ul>
12 12 <% end %>
... ...
app/views/blocks/link_list.html.erb
... ... @@ -8,7 +8,7 @@
8 8 <%= block.sanitize_link(link_to(link[:name], block.expand_address(link[:address]),
9 9 :target => link[:target],
10 10 :class => (link[:icon] ? "icon-#{link[:icon]}" : ''),
11   - :title => link[:title])) %>
  11 + :title => link[:title])).html_safe %>
12 12 </li>
13 13 <% end %>
14 14 </ul>
... ...
app/views/blocks/login.html.erb
... ... @@ -3,7 +3,7 @@
3 3 <h2><%= _('Logged in as %s') % user.identifier %></h2>
4 4 <ul>
5 5 <li><%= _('User since %s/%s') % [user.created_at.month, user.created_at.year] %></li>
6   - <li><%= link_to _('Homepage'), user.public_profile_url %></li>
  6 + <li><%= link_to _('Homepage'), url_for(user.public_profile_url) %></li>
7 7 </ul>
8 8 <div class="user-actions">
9 9 <%= button(:'menu-logout', _('Logout'), :controller => 'account', :action => 'logout') %>
... ...
app/views/blocks/profile_list.html.erb
... ... @@ -10,8 +10,8 @@
10 10 <% if list.empty? %>
11 11 <div class='common-profile-list-block-none'><%= _('None') %></div>
12 12 <% else %>
13   - <ul><%= list %></ul>
  13 + <ul><%= list.html_safe %></ul>
14 14 <% end %>
15 15 </div>
16   -
  16 +
17 17 <br style='clear:both'/>
... ...
app/views/box_organizer/_article_block.html.erb
... ... @@ -9,7 +9,8 @@
9 9 first_text = articles[articles.find_index{|a| a.kind_of? TextArticle}||-1]
10 10 selected = @block.article || first_text
11 11 %>
12   - <%= select_tag(
  12 + <%=
  13 + select_tag(
13 14 'block[article_id]',
14 15 options_for_select_with_title(articles.map {|item| [item.path, item.id]}, selected.id),
15 16 :onchange => 'this.changedTo(this.value)'
... ...
app/views/catalog/index.html.erb
... ... @@ -35,7 +35,7 @@
35 35 <% else %>
36 36 <div class="no-image"><%= _('No image') %></div>
37 37 <% end %>
38   - <div class="catalog-item-extras"><%= extra_content.join("\n") %></div>
  38 + <div class="catalog-item-extras"><%= safe_join(extra_content, "\n") %></div>
39 39 </li>
40 40  
41 41 <li class="product-link"><%= link_to_product product %></li>
... ...
app/views/cms/_blog.html.erb
... ... @@ -35,7 +35,7 @@
35 35 <div id="article-formitem">
36 36 <%= labelled_form_field( _('Address'),
37 37 content_tag('code',
38   - url_for(@article.url).gsub(/#{@article.slug}$/, '') +
  38 + url_for(@article.url).gsub(/#{@article.slug}$/, '').html_safe +
39 39 text_field(:article, :slug, :onchange => "warn_value_change()", :size => 25)
40 40 ) +
41 41 content_tag('div',
... ...
app/views/cms/_textile_quick_reference.html.erb
... ... @@ -14,7 +14,7 @@
14 14 <p><%= _('Numbered lists:') %></p>
15 15 <pre># <%= _('first item') %>
16 16 # <%= _('second item') %></pre>
17   - <p><%= h(_('For code, use HTML tags <pre> and <code>, and indent the code inside them:')) %>
  17 + <p><%= h(_('For code, use HTML tags <pre> and <code>, and indent the code inside them:').html_safe) %>
18 18 </p>
19 19 <pre>
20 20 &lt;pre&gt;
... ... @@ -23,7 +23,7 @@
23 23 &lt;/code&gt;
24 24 &lt;/pre&gt;
25 25 </pre>
26   - <p><%= _('See also a more complete <a href="%s">Textile Reference</a>.') % 'http://redcloth.org/hobix.com/textile/' %></p>
  26 + <p><%= _('See also a more complete <a href="%s">Textile Reference</a>.').html_safe % 'http://redcloth.org/hobix.com/textile/' %></p>
27 27 </div>
28 28 </div>
29 29  
... ...
app/views/cms/edit.html.erb
... ... @@ -39,7 +39,7 @@
39 39  
40 40 <script>
41 41 jQuery('#article_tag_list').inputosaurus({
42   - autoCompleteSource: <%= "'/myprofile/#{profile.identifier}/cms/search_tags'," %>
  42 + autoCompleteSource: <%= "'/myprofile/#{profile.identifier}/cms/search_tags',".html_safe %>
43 43 activateFinalResult : true
44 44 })
45 45 </script>
... ...
app/views/cms/select_article_type.html.erb
... ... @@ -5,7 +5,7 @@
5 5 <ul class="article-types">
6 6 <% for type in @article_types %>
7 7 <% action = type[:class].name == 'UploadedFile' ? {:action => 'upload_files'} : {:action => 'new', :type => type[:class].name} %>
8   - <%= content_tag('a', :href => url_for(action.merge(:parent_id => @parent_id, :back_to => @back_to))) do %>
  8 + <%= content_tag('a', :href => url_for(action.merge(:parent_id => @parent_id, :back_to => @back_to)).html_safe) do %>
9 9 <li class="<%= icon_for_new_article(type[:class]) %>" onmouseover="javascript: jQuery(this).addClass('mouseover')" onmouseout="jQuery(this).removeClass('mouseover')">
10 10 <strong><%= type[:short_description] %></strong>
11 11 <div class='description'><%= type[:description] %></div>
... ...
app/views/cms/upload_files.html.erb
... ... @@ -17,11 +17,11 @@
17 17 <h3><%= _("Select the files you want to upload (max size %s):") % UploadedFile.max_size.to_humanreadable %></h3>
18 18 <h4><%= _('Documents, Images, Videos, Audio') %></h4>
19 19  
20   -<h5><%= _('Uploading files to %s') % content_tag('code', @target) %></h5>
  20 +<h5><%= (_('Uploading files to %s') % content_tag('code', @target)).html_safe%></h5>
21 21  
22 22 <%= form_for('uploaded_file', :url => { :action => 'upload_files' }, :html => {:multipart => true}) do |f| %>
23 23  
24   - <%= @plugins.dispatch(:upload_files_extra_fields, params[:parent_id]).collect { |content| instance_exec(&content) }.join("") %>
  24 + <%= safe_join(@plugins.dispatch(:upload_files_extra_fields, params[:parent_id]).collect { |content| instance_exec(&content) }, "") %>
25 25  
26 26 <%= render :partial => 'upload_file_form', :locals => { :size => '45'} %>
27 27  
... ...
app/views/cms/view.html.erb
... ... @@ -17,7 +17,7 @@
17 17 <% button_bar(:style => 'margin-bottom: 1em;') do %>
18 18 <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %>
19 19  
20   - <%= modal_button('new', _('New content'), :action => 'new', :parent_id => parent_id, :cms => true) %>
  20 + <%= modal_button('new', _('New content'), url_for({:action => 'new', :parent_id => parent_id, :cms => true}).html_safe) %>
21 21 <%= button(:back, _('Back to control panel'), :controller => 'profile_editor', :action => "index") %>
22 22 <% end %>
23 23  
... ... @@ -26,7 +26,7 @@
26 26 <strong><%= _('Current folder: ') %></strong>
27 27 <%= link_to profile.identifier, :action => 'index' %>
28 28 <% @article.hierarchy.each do |item| %>
29   - <%= " / " + ((item == @article) ? item.name.html_safe : link_to(item.slug, :id => item.id).html_safe) %>
  29 + <%= " / ".html_safe + ((item == @article) ? item.name.html_safe : link_to(item.slug, :id => item.id).html_safe) %>
30 30 <% end %>
31 31 </div>
32 32 <% end %>
... ... @@ -45,9 +45,9 @@
45 45 <tr>
46 46 <td>
47 47 <% if @article.parent %>
48   - <%= link_to '.. (' + _('parent folder') + ')', {:action => 'view', :id => @article.parent.id}, :class => 'icon-parent-folder' %>
  48 + <%= link_to '.. ('.html_safe + _('parent folder') + ')', {:action => 'view', :id => @article.parent.id}, :class => 'icon-parent-folder' %>
49 49 <% else %>
50   - <%= link_to '.. (' + _('parent folder') + ')', {:action => 'index'}, :class => 'icon-parent-folder' %>
  50 + <%= link_to '.. ('.html_safe + _('parent folder') + ')', {:action => 'index'}, :class => 'icon-parent-folder' %>
51 51 <% end %>
52 52 </td>
53 53 <td><%= Folder.short_description %></td>
... ...
app/views/comment/_comment.html.erb
... ... @@ -43,7 +43,7 @@
43 43 <p/>
44 44 <%= txt2html comment.body %>
45 45 </div>
46   - <%= @plugins.dispatch(:comment_extra_contents, local_assigns).collect { |content| instance_exec(&content) }.join("") %>
  46 + <%= safe_join(@plugins.dispatch(:comment_extra_contents, local_assigns).collect { |content| instance_exec(&content) }, "") %>
47 47 </div>
48 48  
49 49 <div class="comment_reply post_comment_box closed" id="comment_reply_to_<%= comment.id %>">
... ...
app/views/comment/_comment_form.html.erb
... ... @@ -85,7 +85,7 @@ function check_captcha(button, confirm_action) {
85 85 <%= hidden_field_tag(:view, params[:view])%>
86 86 <%= f.hidden_field(:reply_of_id) %>
87 87  
88   - <%= @plugins.dispatch(:comment_form_extra_contents, local_assigns.merge(:comment => @comment)).collect { |content| instance_exec(&content) }.join("") %>
  88 + <%= safe_join(@plugins.dispatch(:comment_form_extra_contents, local_assigns.merge(:comment => @comment)).collect { |content| instance_exec(&content) }, "") %>
89 89  
90 90 <% button_bar do %>
91 91 <%= submit_button('add', _('Post comment'), :onclick => "if(check_captcha(this)) { save_comment(this) } else { check_captcha(this, save_comment)};return false;") %>
... ...
app/views/content_viewer/_article_toolbar.html.erb
... ... @@ -26,7 +26,7 @@
26 26 <% content = _('Add translation') %>
27 27 <% parent_id = (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)) %>
28 28 <% url = profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => parent_id, :type => @page.type, :article => { :translation_of_id => @page.native_translation.id })%>
29   - <%= expirable_button @page, :locale, content, url %>
  29 + <%= expirable_button @page, :locale, content, url_for(url).html_safe %>
30 30 <% end %>
31 31  
32 32 <% if !@page.archived? %>
... ... @@ -67,7 +67,7 @@
67 67 <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div>
68 68 <% end %>
69 69 <%= button_without_text(:feed, _('RSS feed'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %>
70   - <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %>
  70 + <%= safe_join(@plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }) %>
71 71 <% if @page.archived? %>
72 72 <%= render :partial => 'cms/archived_warning', :locals => {:article => @page} %>
73 73 <% end %>
... ...
app/views/content_viewer/_publishing_info.html.erb
... ... @@ -7,7 +7,7 @@
7 7 </span>
8 8 <% unless @no_comments %>
9 9 <span class="comments">
10   - <%= (" - %s") % link_to_comments(@page)%>
  10 + <%= (" - %s").html_safe % link_to_comments(@page) %>
11 11 </span>
12 12 <% end %>
13 13  
... ...
app/views/content_viewer/event_page.html.erb
... ... @@ -35,7 +35,7 @@
35 35 </div>
36 36 <% end %>
37 37 <div class="event-content">
38   - <%= event.body %>
  38 + <%= raw event.body %>
39 39 </div>
40 40 <% end %>
41 41 </div>
... ...
app/views/content_viewer/versions_diff.html.erb
... ... @@ -2,9 +2,9 @@
2 2 <%= button(:back, _('Back to the versions'), {:action => 'article_versions'}) %>
3 3 </div>
4 4  
5   -<h1><%= _('Changes on "%s"') % @page.title %></h1>
  5 +<h1><%= _('Changes on "%s"').html_safe % @page.title %></h1>
6 6  
7   -<p> <%= _('Changes from %s &rarr; %s') % [show_time(@v1.updated_at), show_time(@v2.updated_at)] %> </p>
  7 +<p> <%= _('Changes from %s &rarr; %s').html_safe % [show_time(@v1.updated_at), show_time(@v2.updated_at)] %> </p>
8 8  
9 9 <% diffContent = Diffy::Diff.new(@v1.body, @v2.body, :context => 1) %>
10 10 <% if diffContent.to_s(:text).blank? %>
... ... @@ -12,5 +12,5 @@
12 12 <%= _('These versions range have no differences.')%>
13 13 </p>
14 14 <% else %>
15   - <%= diffContent.to_s(:html) %>
  15 + <%= diffContent.to_s(:html).html_safe %>
16 16 <% end %>
... ...
app/views/content_viewer/view_page.html.erb
... ... @@ -45,24 +45,24 @@
45 45 <% if ! @page.categories.empty? %>
46 46 <div id="article-cat">
47 47 <h4><%= _('Categories') %></h4>
48   - <%= @page.categories.map {|item| link_to_category(item, false) }.join(", ") %>
  48 + <%= safe_join(@page.categories.map {|item| link_to_category(item, false) }, ", ") %>
49 49 </div>
50 50 <% end %>
51 51  
52 52 <% if !@page.tags.empty? %>
53 53 <div id="article-tags">
54   - <%= _("This article's tags:") %>
55   - <%= @page.tags.map { |t| link_to(t, :controller => 'profile', :profile => @profile.identifier, :action => 'tags', :id => t.name ) }.join("\n") %>
  54 + <%= _("This article's tags:").html_safe %>
  55 + <%= safe_join(@page.tags.map { |t| link_to(t, :controller => 'profile', :profile => @profile.identifier, :action => 'tags', :id => t.name ) }, "\n") %>
56 56 </div>
57 57 <% end %>
58 58  
59 59 <%= display_source_info(@page) %>
60 60  
61   -<%= @plugins.dispatch(:article_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %>
  61 +<%= safe_join(@plugins.dispatch(:article_extra_contents, @page).collect { |content| instance_exec(&content) }, "") %>
62 62  
63 63 <% if @page.accept_comments? || @comments_count > 0 %>
64 64 <div class="comments" id="comments_list">
65   - <h3 <%= 'class="no-comments-yet"' if @comments_count == 0 %>>
  65 + <h3 <%= 'class="no-comments-yet"'.html_safe if @comments_count == 0 %>>
66 66 <%= display_number_of_comments(@comments_count) %>
67 67 </h3>
68 68  
... ...
app/views/doc/_toc.html.erb
... ... @@ -5,5 +5,5 @@
5 5 <li><%= link_to text, link, :target => '_blank' %></li>
6 6 <% end %>
7 7 </ul>
8   - <%= @toc.text %>
  8 + <%= raw @toc.text %>
9 9 </div>
... ...
app/views/features/index.html.erb
... ... @@ -5,7 +5,7 @@
5 5 <p>
6 6 <%= _('Here you can enable or disable several features of your environment. Each feature represents some funcionality that your environment can use if you enable it.
7 7  
8   -Check all the features you want to enable for your environment, uncheck all the ones you don\'t want, and use the <em>"Save changes" button</em> to confirm your changes.') %>
  8 +Check all the features you want to enable for your environment, uncheck all the ones you don\'t want, and use the <em>"Save changes" button</em> to confirm your changes.').html_safe %>
9 9 </p>
10 10  
11 11 <%= labelled_form_for(:environment, :url => {:action => 'update'}) do |f| %>
... ...
app/views/home/index.html.erb
... ... @@ -7,7 +7,7 @@
7 7 <div class='highlighted-news-item post-<%= index + 1 %>-inner'>
8 8 <h2><%= link_to(h(highlighted.title), highlighted.url, :class => 'post-title') %></h2>
9 9 <span class="post-date"><%= show_date(highlighted.published_at, true) %> </span>
10   - <div class='headline'><%= highlighted.lead %></div>
  10 + <div class='headline'><%= raw highlighted.lead %></div>
11 11 <p class='highlighted-news-read-more'>
12 12 <%= link_to(_('Read more'), highlighted.url) %>
13 13 </p>
... ... @@ -49,7 +49,7 @@
49 49 <% end %>
50 50 <% end %>
51 51 <% else %>
52   - <%= environment.description %>
  52 + <%= environment.description.html_safe %>
53 53 <% end %>
54 54  
55 55 <% if environment.enabled?('search_in_home') %>
... ...
app/views/invite/_select_address_book.html.erb
... ... @@ -3,12 +3,12 @@
3 3  
4 4 <%= form_tag do %>
5 5  
6   - <%= [
  6 + <%= safe_join([
7 7 radio_button_tag(:import_from, "manual", @import_from == "manual", :onclick => 'hide_invite_friend_login_password()') + content_tag('label', _('Manually (empty field)'), :for => "import_from_manual"),
8 8 radio_button_tag(:import_from, "gmail", @import_from == "gmail", :onclick => 'show_invite_friend_login_password(this.value)') + content_tag('label', 'Gmail', :for => 'import_from_gmail'),
9 9 radio_button_tag(:import_from, "yahoo", @import_from == "yahoo", :onclick => 'show_invite_friend_login_password(this.value)') + content_tag('label', 'Yahoo', :for => "import_from_yahoo"),
10 10 radio_button_tag(:import_from, "hotmail", @import_from == "hotmail", :onclick => 'show_invite_friend_login_password(this.value)') + content_tag('label', 'Hotmail', :for => "import_from_hotmail")
11   - ].join("\n<br/>\n") %>
  11 + ], "\n<br/>\n".html_safe) %>
12 12  
13 13 <script type="text/javascript">
14 14 function hide_invite_friend_login_password() {
... ...
app/views/layouts/_user.html.erb
... ... @@ -7,22 +7,23 @@
7 7 </span>
8 8 <% else %>
9 9 <span class='not-logged-in'>
10   - <%= _("<span class='login'>%s</span>") % modal_inline_link_to('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, '#inlineLoginBox', :id => 'link_login') %>
11   - <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_exec(&content) }.join("") %>
  10 + <%= usermenu_notlogged_in %>
  11 + <% @plugins.dispatch(:alternative_authentication_link).collect do |content|%>
  12 + <%= instance_exec(&content) %>
  13 + <%end%>
12 14  
13   - <div id='inlineLoginBox' style='display: none;'>
14   - <%= render :file => 'account/login', :locals => { :is_popin => true } %>
15   - </div>
  15 + <div id='inlineLoginBox' style='display: none;'>
  16 + <%= render :file => 'account/login', :locals => { :is_popin => true } %>
  17 + </div>
16 18  
17   - <% unless @plugins.dispatch(:allow_user_registration).include?(false) %>
18   - <%= _("<span class='or'>or</span> <span class='signup'>%s</span>") % link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup')%>
19   - <% end %>
20   -
21   - </span>
  19 + <% unless @plugins.dispatch(:allow_user_registration).include?(false) %>
  20 + <%= usermenu_signup %>
  21 + <% end %>
  22 + </span>
22 23 <% end %>
23 24 <form action="/search/articles" id="top-search" class="search_form clean" method="get">
24 25 <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" />
25   - <div><%=_('Press <strong>Enter</strong> to send the search query.')%></div>
  26 + <div><%=_('Press <strong>Enter</strong> to send the search query.').html_safe%></div>
26 27 <%= javascript_tag 'jQuery("#user form input").hint();' %>
27 28 </form>
28 29 </div><!-- end id="user" -->
... ...
app/views/layouts/application-ng.html.erb
1 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= html_language %>" lang="<%= html_language %>" class="<%= h html_tag_classes %>">
3 3 <head>
4   - <title><%= h page_title %></title>
  4 + <title><%= h page_title.html_safe %></title>
5 5 <%= yield(:feeds) %>
6 6 <!--<meta http-equiv="refresh" content="1"/>-->
7 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
... ... @@ -20,24 +20,33 @@
20 20 <%# Add custom tags/styles/etc via content_for %>
21 21 <%= yield :head %>
22 22 <%=
23   - @plugins.dispatch(:head_ending).map do |content|
24   - if content.respond_to?(:call) then instance_exec(&content).to_s.html_safe else content.to_s.html_safe end
25   - end.join("\n")
  23 + str = (@plugins.dispatch(:head_ending).map do |content|
  24 + if content.respond_to?(:call) then
  25 + instance_exec(&content).to_s
  26 + else
  27 + content.to_s
  28 + end
  29 + end)
  30 + safe_join(str, "\n")
26 31 %>
27 32  
28 33 <script type="text/javascript">
29   - DEFAULT_LOADING_MESSAGE = <%="'#{ _('loading...') }'" %>;
30   - noosfero.profile = <%= (@profile.identifier if @profile).to_json %>
  34 + DEFAULT_LOADING_MESSAGE = <%="'#{ _('loading...') }'".html_safe %>;
  35 + noosfero.profile = <%= (@profile.identifier if @profile).to_json.html_safe %>
31 36 </script>
32 37  
33 38 </head>
34 39 <body class="<%= h body_classes %>">
35 40 <a href="#content" id="link-go-content"><span><%= _("Go to the content") %></span></a>
36   -
37 41 <%=
38   - @plugins.dispatch(:body_beginning).map do |content|
39   - if content.respond_to?(:call) then instance_exec(&content).to_s.html_safe else content.to_s.html_safe end
40   - end.join("\n")
  42 + str = (@plugins.dispatch(:body_beginning).map do |content|
  43 + if content.respond_to?(:call) then
  44 + instance_exec(&content).to_s
  45 + else
  46 + content.to_s
  47 + end
  48 + end)
  49 + safe_join(str, "\n")
41 50 %>
42 51 <div id="global-header">
43 52 <%= global_header %>
... ... @@ -75,9 +84,14 @@
75 84 <%= noosfero_layout_features %>
76 85 <%= addthis_javascript %>
77 86 <%=
78   - @plugins.dispatch(:body_ending).map do |content|
79   - if content.respond_to?(:call) then instance_exec(&content).html_safe else content.html_safe end
80   - end.join("\n")
  87 + str = (@plugins.dispatch(:body_ending).map do |content|
  88 + if content.respond_to?(:call) then
  89 + instance_exec(&content)
  90 + else
  91 + content
  92 + end
  93 + end)
  94 + safe_join(str, "\n")
81 95 %>
82 96 </body>
83 97 </html>
... ...
app/views/mailconf/index.html.erb
... ... @@ -16,7 +16,7 @@
16 16 <% if profile.user.enable_email %>
17 17 <h2><%= ('E-mail address') %></h2>
18 18 <ul>
19   - <%= profile.email_addresses.map{|i| content_tag('li', i)}.join("\n") %>
  19 + <%= safe_join(profile.email_addresses.map{|i| content_tag('li', i)}, "\n") %>
20 20 </ul>
21 21 <h2><%= _('Configuration') %></h2>
22 22 <ul>
... ... @@ -31,7 +31,7 @@
31 31 <% else %>
32 32  
33 33 <h2><%= _("Enable e-Mail account below:") %></h2>
34   - <ul><%= profile.email_addresses.map{|i| content_tag('li', i)}.join("\n") %></ul>
  34 + <ul><%= safe_join(profile.email_addresses.map{|i| content_tag('li', i)}, "\n") %></ul>
35 35 <blockquote><%= _("You'll be able to access a webmail from your user menu.") %></blockquote>
36 36 <% button_bar do %>
37 37 <%= button(:ok, _('Enable e-Mail'), { :action => 'enable' }, :method => 'post') %>
... ...
app/views/mailing/sender/notification.html.erb
... ... @@ -4,7 +4,7 @@
4 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5 5 </head>
6 6 <body style="margin: 0">
7   - <%= word_wrap(@message) %>
  7 + <%= raw word_wrap(@message) %>
8 8 <p>
9 9 --<br/>
10 10 <%= @signature_message %><br/>
... ...
app/views/manage_products/show.html.erb
... ... @@ -14,7 +14,7 @@
14 14 </div>
15 15 <div id='product-extra-content'>
16 16 <% extra_content = @plugins.dispatch(:product_info_extras, @product).collect { |content| instance_exec(&content) } %>
17   - <%= extra_content.join("\n") %>
  17 + <%= safe_join(extra_content, "\n") %>
18 18 </div>
19 19 <div id='product-info'>
20 20 <%= render :partial => 'manage_products/display_info' %>
... ...
app/views/memberships/new_community.html.erb
... ... @@ -34,13 +34,13 @@
34 34 <div style='margin-bottom: 0.5em' id='community-join-before'>
35 35 <%= radio_button 'community', 'closed', 'true', :style => 'float: left' %>
36 36 <div style='margin-left: 30px'>
37   - <%= _('<strong>Before</strong> joining this group (a moderator has to accept the member in pending request before member can access the intranet and/or the website).') %>
  37 + <%= _('<strong>Before</strong> joining this group (a moderator has to accept the member in pending request before member can access the intranet and/or the website).').html_safe %>
38 38 </div>
39 39 </div>
40 40 <div id='community-join-after'>
41 41 <%= radio_button 'community', 'closed', 'false', :style => 'float: left' %>
42 42 <div style='margin-left: 30px'>
43   - <%= _('<strong>After</strong> joining this group (a moderator can always desactivate access for users later).') %>
  43 + <%= _('<strong>After</strong> joining this group (a moderator can always desactivate access for users later).').html_safe %>
44 44 </div>
45 45 </div>
46 46  
... ...
app/views/pending_task_notifier/notification.text.erb
... ... @@ -2,7 +2,7 @@
2 2  
3 3 <%= _("You have %d pending task(s).") % @tasks.size %>
4 4  
5   -<%= @tasks.map{|i| " * #{i.description}"}.join("\n") %>
  5 +<%= safe_join(@tasks.map{|i| " * #{i.description}"}, "\n") %>
6 6  
7 7 <%= _("Click in address below to process task(s):") %>
8 8  
... ... @@ -11,7 +11,7 @@
11 11 <% pending_tasks = @person.pending_tasks_for_organization(organization) %>
12 12 <%= _("%s has %d pending task(s).") % [organization.name, pending_tasks.size] %>
13 13  
14   -<%= pending_tasks.map{|i| " * #{i.information}"}.join("\n") %>
  14 +<%= safe_join(pending_tasks.map{|i| " * #{i.information}"}, "\n") %>
15 15  
16 16 <%= _("Click in address below to process task(s):") %>
17 17  
... ...
app/views/profile/content_tagged.html.erb
... ... @@ -20,6 +20,6 @@
20 20 <%= pagination_links @tagged, :param_name => 'npage' %>
21 21  
22 22 <div>
23   - <%= link_to _('See content tagged with "%s" in the entire site') % escaped_tag, :controller => 'search', :action => 'tag', :tag => @tag %>
  23 + <%= link_to (_('See content tagged with "%s" in the entire site') % escaped_tag).html_safe, :controller => 'search', :action => 'tag', :tag => @tag %>
24 24 </div>
25 25 <% end %>
... ...
app/views/profile/index.html.erb
... ... @@ -5,7 +5,7 @@
5 5 <% else %>
6 6 <% unless profile.description.blank? %>
7 7 <div class='public-profile-description'>
8   - <%= profile.description %>
  8 + <%= raw profile.description %>
9 9 </div>
10 10 <% end %>
11 11 <div id='public-profile-search'>
... ...
app/views/profile_editor/_moderation.html.erb
... ... @@ -34,13 +34,13 @@
34 34 <div style='margin-bottom: 0.5em'>
35 35 <%= radio_button 'profile_data', 'closed', 'true', :style => 'float: left' %>
36 36 <div style='margin-left: 30px'>
37   - <%= _('<strong>Before</strong> joining this group (a moderator has to accept the member in pending request before member can access the intranet and/or the website).') %>
  37 + <%= _('<strong>Before</strong> joining this group (a moderator has to accept the member in pending request before member can access the intranet and/or the website).').html_safe %>
38 38 </div>
39 39 </div>
40 40 <div>
41 41 <%= radio_button 'profile_data', 'closed', 'false', :style => 'float: left' %>
42 42 <div style='margin-left: 30px'>
43   - <%= _('<strong>After</strong> joining this group (a moderator can always desactivate access for users later).') %>
  43 + <%= _('<strong>After</strong> joining this group (a moderator can always desactivate access for users later).').html_safe %>
44 44 </div>
45 45 </div>
46 46 <br>
... ... @@ -52,13 +52,13 @@
52 52 <div style='margin-bottom: 0.5em'>
53 53 <%= radio_button 'profile_data', 'moderated_articles', 'true', :style => 'float: left' %>
54 54 <div style='margin-left: 30px'>
55   - <%= _('<strong>Before</strong> being published in this group (a moderator has to accept the article in pending request before the article be listed as a article of this group).') %>
  55 + <%= _('<strong>Before</strong> being published in this group (a moderator has to accept the article in pending request before the article be listed as a article of this group).').html_safe %>
56 56 </div>
57 57 </div>
58 58 <div>
59 59 <%= radio_button 'profile_data', 'moderated_articles', 'false', :style => 'float: left' %>
60 60 <div style='margin-left: 30px'>
61   - <%= _('<strong>After</strong> being published in this group (a moderator can always remove publicated articles later).') %>
  61 + <%= _('<strong>After</strong> being published in this group (a moderator can always remove publicated articles later).').html_safe %>
62 62 </div>
63 63 </div>
64 64  
... ...
app/views/profile_editor/_organization.html.erb
... ... @@ -4,7 +4,7 @@
4 4  
5 5 <%= required f.text_field(:name) %>
6 6  
7   - <%= @plugins.dispatch(:profile_info_extra_contents).collect { |content| instance_exec(&content) }.join("") %>
  7 + <%= safe_join(@plugins.dispatch(:profile_info_extra_contents).collect { |content| instance_exec(&content) }, "") %>
8 8  
9 9 <% if @environment.enabled?('enable_organization_url_change') %>
10 10 <script type="text/javascript">
... ... @@ -41,7 +41,7 @@
41 41 <div id="profile-identifier-formitem">
42 42 <%= required labelled_form_field( _('Address'),
43 43 content_tag('code',
44   - url_for(profile.url).gsub(/#{profile.identifier}$/, '') +
  44 + url_for(profile.url).gsub(/#{profile.identifier}$/, '').html_safe +
45 45 text_field(:profile_data, :identifier, :onchange => "warn_value_change()", :size => 25)
46 46 ) +
47 47 content_tag('div',
... ...
app/views/profile_editor/_pending_tasks.html.erb
... ... @@ -4,7 +4,7 @@
4 4 <div class='pending-tasks'>
5 5 <h2><%= _('You have pending requests') %></h2>
6 6 <ul>
7   - <%= @pending_tasks.map {|task| content_tag('li', task_information(task))}.join %>
  7 + <%= safe_join(@pending_tasks.map {|task| content_tag('li', task_information(task))}) %>
8 8 </ul>
9 9 <%= button(:todo, _('Process requests'), :controller => 'tasks', :action => 'index') %>
10 10 </div>
... ...
app/views/profile_editor/_person.html.erb
... ... @@ -16,7 +16,7 @@
16 16 </div>
17 17 </div>
18 18  
19   - <%= @plugins.dispatch(:profile_info_extra_contents).collect { |content| instance_exec(&content) }.join("") %>
  19 + <%= safe_join(@plugins.dispatch(:profile_info_extra_contents).collect { |content| instance_exec(&content) }, "") %>
20 20  
21 21 <div class="formfieldline">
22 22 <%= label_tag("private_token", _("Private Token")) %>
... ...
app/views/profile_editor/edit.html.erb
... ... @@ -26,20 +26,20 @@
26 26  
27 27 <% if profile.person? %>
28 28 <div>
29   - <%= labelled_radio_button _('Public &mdash; show my contents to all internet users'), 'profile_data[public_profile]', true, @profile.public_profile? %>
  29 + <%= labelled_radio_button _('Public &mdash; show my contents to all internet users').html_safe, 'profile_data[public_profile]', true, @profile.public_profile? %>
30 30 </div>
31 31 <div>
32   - <%= labelled_radio_button _('Private &mdash; show my contents only to friends'), 'profile_data[public_profile]', false, !@profile.public_profile? %>
  32 + <%= labelled_radio_button _('Private &mdash; show my contents only to friends').html_safe, 'profile_data[public_profile]', false, !@profile.public_profile? %>
33 33 </div>
34 34 <% else %>
35 35 <div>
36   - <%= labelled_check_box _("Secret &mdash; hide the community and all its contents for non members and other people can't join this community unless they are invited to."), 'profile_data[secret]', true, profile.secret, :class => "profile-secret-box" %>
  36 + <%= labelled_check_box _("Secret &mdash; hide the community and all its contents for non members and other people can't join this community unless they are invited to.").html_safe, 'profile_data[secret]', true, profile.secret, :class => "profile-secret-box" %>
37 37 </div>
38 38 <div>
39   - <%= labelled_radio_button _('Public &mdash; show content of this group to all internet users'), 'profile_data[public_profile]', true, @profile.public_profile?, :class => "public-community-button" %>
  39 + <%= labelled_radio_button _('Public &mdash; show content of this group to all internet users').html_safe, 'profile_data[public_profile]', true, @profile.public_profile?, :class => "public-community-button" %>
40 40 </div>
41 41 <div>
42   - <%= labelled_radio_button _('Private &mdash; show content of this group only to members'), 'profile_data[public_profile]', false, !@profile.public_profile?, :class => "private-community-button" %>
  42 + <%= labelled_radio_button _('Private &mdash; show content of this group only to members').html_safe, 'profile_data[public_profile]', false, !@profile.public_profile?, :class => "private-community-button" %>
43 43 </div>
44 44 <% end %>
45 45  
... ... @@ -60,9 +60,9 @@
60 60 )%>
61 61  
62 62 <%=
63   - @plugins.dispatch(:profile_editor_extras).map do |content|
  63 + safe_join(@plugins.dispatch(:profile_editor_extras).map do |content|
64 64 content.kind_of?(Proc) ? self.instance_exec(&content) : content
65   - end.join("\n")
  65 + end, "\n")
66 66 %>
67 67  
68 68 <%= select_categories(:profile_data, _('Select the categories of your interest'), 2) %>
... ...
app/views/profile_members/_members_filter.erb
... ... @@ -7,7 +7,7 @@
7 7  
8 8 <p><%= _('Roles:') %> </p>
9 9 <% @data[:roles].each do |r| %>
10   - <%= labelled_check_box(r.name, 'filters[roles][]', r.id, @filters[:roles].include?(r.id.to_s), :add_hidden => false) %><br/>
  10 + <%= raw labelled_check_box(r.name, 'filters[roles][]', r.id, @filters[:roles].include?(r.id.to_s), :add_hidden => false) %><br/>
11 11 <% end %>
12 12 <p>
13 13 <%= submit_button(:search, _('Search')) %>
... ...
app/views/search/_article_last_change.html.erb
... ... @@ -2,7 +2,7 @@
2 2  
3 3 <div class="search-article-author-changes">
4 4 <% if article.last_changed_by and article.last_changed_by != article.profile %>
5   - <span><%= _('Updated by %{name} at %{date}') % {:name => link_to(article.last_changed_by.name, article.last_changed_by.url),
  5 + <span><%= _('Updated by %{name} at %{date}').html_safe % {:name => link_to(article.last_changed_by.name, article.last_changed_by.url),
6 6 :date => show_date(article.updated_at) } %></span>
7 7 <% else %>
8 8 <span><%= _('Last update: %s.') % show_date(article.updated_at) %></span>
... ...
app/views/search/_full_product.html.erb
1 1 <% extra_content = @plugins.dispatch(:asset_product_extras, product).collect { |content| instance_exec(&content) } %>
2   -<% extra_properties = @plugins.dispatch(:asset_product_properties, product)%>
  2 +<% extra_properties = @plugins.dispatch(:asset_product_properties, product) %>
3 3  
4 4 <li class="search-product-item <%= 'highlighted' if product.highlighted? %>">
5 5  
... ... @@ -77,9 +77,9 @@
77 77  
78 78 <div style="clear: both"></div>
79 79  
80   - <%= extra_content.join('\n') %>
  80 + <%= safe_join(extra_content, '\n') %>
81 81 <% extra_properties.each do |property| %>
82   - <div><%= property[:name] + ': ' + instance_exec(&property[:content]) %></div>
  82 + <div><%= ''.html_safe + property[:name] + ': ' + instance_exec(&property[:content]) %></div>
83 83 <% end %>
84 84  
85 85 </li>
... ...
app/views/search/tag.html.erb
1 1 <h2>
2   - <%= _('Tagged with "%s"') % content_tag('code', @tag) %>
  2 + <%= _('Tagged with "%s"').html_safe % content_tag('code', @tag) %>
3 3 </h2>
4 4  
5 5 <% button_bar do %>
... ...
app/views/shared/_list_groups.html.erb
... ... @@ -6,9 +6,9 @@
6 6 </div>
7 7 <span class='profile-details'>
8 8 <strong><%= group.name %></strong><br/>
9   - <%= _('Role: %s') % rolename_for(profile, group) + '<br/>' if profile.role_assignments.find_by(resource_id: group.id) %>
  9 + <%= raw _('Role: %s') % rolename_for(profile, group) + '<br/>' if profile.role_assignments.find_by(resource_id: group.id) %>
10 10 <%= _('Type: %s') % _(group.class.identification) %> <br/>
11   - <%= _('Description: %s') % group.description + '<br/>' if group.community? %>
  11 + <%= raw _('Description: %s') % group.description + '<br/>' if group.community? %>
12 12 <%= _('Members: %s') % group.members_count.to_s %> <br/>
13 13 <%= _('Created at: %s') % show_date(group.created_at) unless group.enterprise? %> <br/>
14 14 <% button_bar do %>
... ...
app/views/tasks/_add_member_accept_details.html.erb
1 1 <%= content = _("Roles:")+"<br />"
2 2 roles = Profile::Roles.organization_member_roles(task.target.environment.id) + profile.custom_roles
3 3 roles.each do |role|
4   - content += labelled_check_box(role.name, "tasks[#{task.id}][task][roles][]", role.id, false)+"<br />"
  4 + content += labelled_check_box(role.name, "tasks[#{task.id}][task][roles][]", role.id, false) + "<br />".html_safe
5 5 end
6   -content_tag('p', content, :class => 'member-classify-suggestion')
  6 +content_tag('p', content.html_safe, :class => 'member-classify-suggestion').html_safe
7 7 %>
... ...
app/views/tasks/_task_icon.html.erb
... ... @@ -3,7 +3,7 @@
3 3 if icon_info[:type] == :profile_image
4 4 icon = profile_image(icon_info[:profile], :minor)
5 5 elsif icon_info[:type] == :defined_image
6   - icon = "<img src='#{icon_info[:src]}' alt='#{icon_info[:name]}' />"
  6 + icon = "<img src='#{icon_info[:src]}' alt='#{icon_info[:name]}' />".html_safe
7 7 end
8 8  
9 9 if icon_info[:url]
... ...
app/views/tasks/list_requested.html.erb
... ... @@ -3,7 +3,7 @@
3 3 <ul>
4 4 <% @tasks.each do |task| %>
5 5 <li>
6   - <strong><%= task.respond_to?(:title) ? link_to( task.title, :action => 'ticket_details', :id => task.id) : task.information %></strong><br/>
  6 + <strong><%= task.respond_to?(:title) ? link_to( task.title, :action => 'ticket_details', :id => task.id).html_safe : task.information %></strong><br/>
7 7 <small>
8 8 <%= _('Created:') + ' ' + show_date(task.created_at) %>
9 9 &nbsp; &#151; &nbsp;
... ...
config/initializers/html_safe.rb
... ... @@ -1,10 +0,0 @@
1   -#From: https://github.com/coletivoEITA/noosfero-ecosol/blob/57908cde4fe65dfe22298a8a7f6db5dba1e7cc75/config/initializers/html_safe.rb
2   -
3   -# Disable Rails html autoescaping. This is due to noosfero using too much helpers/models to output html.
4   -# It it would change too much code and make it hard to maintain.
5   -# FIXME THIS IS SO WRONG
6   -class Object
7   - def html_safe?
8   - true
9   - end
10   -end
lib/noosfero/plugin.rb
... ... @@ -611,7 +611,7 @@ class Noosfero::Plugin
611 611 end
612 612  
613 613 # -> Perform extra transactions related to profile in profile editor
614   - # returns = true in success or raise and exception if it could not update the data
  614 + # returns = true in success or raise an exception if it could not update the data
615 615 def profile_editor_transaction_extras
616 616 nil
617 617 end
... ...
plugins/breadcrumbs/lib/breadcrumbs_plugin/content_breadcrumbs_block.rb
... ... @@ -49,7 +49,7 @@ class BreadcrumbsPlugin::ContentBreadcrumbsBlock &lt; Block
49 49  
50 50 def content(args={})
51 51 block = self
52   - proc do
  52 + ret = (proc do
53 53 trail = block.trail(@page, @profile, params)
54 54 if !trail.empty?
55 55 separator = content_tag('span', ' > ', :class => 'separator')
... ... @@ -63,11 +63,12 @@ class BreadcrumbsPlugin::ContentBreadcrumbsBlock &lt; Block
63 63 breadcrumb << content_tag('div', section_name, :class => 'section-name')
64 64 end
65 65  
66   - breadcrumb
  66 + breadcrumb.html_safe
67 67 else
68 68 ''
69 69 end
70   - end
  70 + end)
  71 + ret
71 72 end
72 73  
73 74 def cacheable?
... ...
plugins/community_block/views/blocks/community.html.erb
... ... @@ -23,7 +23,7 @@
23 23 <%= link_to(
24 24 content_tag('span','',:class => 'community-block-button icon-arrow'),
25 25 '#',
26   - :onclick => "toggleSubmenu(this,'',#{CGI::escapeHTML(links.to_json)}); return false;",
  26 + :onclick => "toggleSubmenu(this,'',#{CGI::escapeHTML(links.to_json)}); return false;".html_safe,
27 27 :class => 'simplemenu-trigger') %>
28 28  
29 29 <% end %>
... ...
plugins/context_content/lib/context_content_plugin/context_content_block.rb
... ... @@ -86,15 +86,16 @@ class ContextContentPlugin::ContextContentBlock &lt; Block
86 86  
87 87 def content(args={})
88 88 block = self
89   - proc do
  89 + ret = proc do
90 90 contents = block.contents(@page)
91 91 parent_title = block.parent_title(contents)
92   - if !contents.blank?
  92 + if contents.present?
93 93 render(:file => 'blocks/context_content', :locals => {:block => block, :contents => contents, :parent_title => parent_title})
94 94 else
95 95 ''
96 96 end
97 97 end
  98 + ret
98 99 end
99 100  
100 101 def cacheable?
... ...
plugins/custom_forms/views/custom_forms_plugin_profile/show.html.erb
... ... @@ -6,9 +6,9 @@
6 6 <% if @submission.id.nil? %>
7 7 <% if @form.expired? %>
8 8 <% if @form.will_open? %>
9   - <h2><%= _('Sorry, you can\'t fill this form yet') %></h2>
  9 + <h2><%= _('Sorry, you can\'t fill this form yet').html_safe %></h2>
10 10 <% else %>
11   - <h2><%= _('Sorry, you can\'t fill this form anymore') %></h2>
  11 + <h2><%= _('Sorry, you can\'t fill this form anymore').html_safe %></h2>
12 12 <% end %>
13 13 <% end %>
14 14  
... ...
plugins/display_content/lib/display_content_block.rb
... ... @@ -177,9 +177,9 @@ class DisplayContentBlock &lt; Block
177 177  
178 178 content_sections += read_more_section if !read_more_section.blank?
179 179 #raise sections.inspect
180   - content_tag('li', content_sections)
  180 + content_tag('li', content_sections.html_safe)
181 181 end
182   - }.join(" "))
  182 + }.join(" ").html_safe)
183 183 end
184 184 end
185 185  
... ...
plugins/event/views/event_plugin/event_block_item.html.erb
... ... @@ -3,11 +3,11 @@
3 3 ev_days_tag = ''
4 4 if event.duration > 1
5 5 ev_days_tag = content_tag('time',
6   - n_('Duration: 1 day', 'Duration: %s days', event.duration) % "<b>#{event.duration}</b>",
  6 + n_('Duration: 1 day', 'Duration: %s days', event.duration).html_safe % "<b>#{event.duration}</b>".html_safe,
7 7 :itemprop => 'endDate',
8 8 :datetime => show_date(event.end_date) + 'T00:00',
9 9 :class => 'duration',
10   - :title => show_date(event.start_date) + ' &mdash; ' + time_left_str
  10 + :title => (show_date(event.start_date) + ' &mdash; ' + time_left_str).html_safe
11 11 )
12 12 end
13 13  
... ... @@ -16,7 +16,7 @@
16 16 img_class = img.blank? ? 'no-img' : 'has-img'
17 17 %>
18 18 <%=
19   - link_to([
  19 + link_to(safe_join([
20 20 content_tag('time',
21 21 block.date_to_html(event.start_date),
22 22 :itemprop => 'startDate',
... ... @@ -33,7 +33,7 @@
33 33 :itemtype => 'http://schema.org/Place',
34 34 :itemprop => :location),
35 35 content_tag('span', time_left_str, :class => 'days-left ' + time_class)
36   - ].join("\n"),
  36 + ], "\n"),
37 37 (event.link.blank? ? event.url : event.link),
38 38 :class => 'ev-days-' + event.duration.to_s,
39 39 :itemprop => :url
... ...
plugins/metadata/lib/metadata_plugin/base.rb
... ... @@ -55,7 +55,7 @@ class MetadataPlugin::Base &lt; Noosfero::Plugin
55 55 end
56 56 end
57 57 end
58   - r.join
  58 + safe_join(r)
59 59 end
60 60 end
61 61  
... ...
plugins/newsletter/lib/newsletter_plugin/newsletter.rb
... ... @@ -110,11 +110,11 @@ class NewsletterPlugin::Newsletter &lt; ApplicationRecord
110 110 include DatesHelper
111 111  
112 112 def message_to_public_link
113   - content_tag(:p, _("If you can't view this email, %s.") % link_to(_('click here'), '{mailing_url}'), :id => 'newsletter-public-link')
  113 + content_tag(:p, (_("If you can't view this email, %s.") % link_to(_('click here'), '{mailing_url}')).html_safe, :id => 'newsletter-public-link').html_safe
114 114 end
115 115  
116 116 def message_to_unsubscribe
117   - content_tag(:div, _("This is an automatically generated email, please do not reply. If you do not wish to receive future newsletter emails, %s.") % link_to(_("cancel your subscription here"), self.unsubscribe_url, :style => CSS['public-link']), :style => CSS['newsletter-unsubscribe'], :id => 'newsletter-unsubscribe')
  117 + content_tag(:div, _("This is an automatically generated email, please do not reply. If you do not wish to receive future newsletter emails, %s.").html_safe % link_to(_("cancel your subscription here"), self.unsubscribe_url, :style => CSS['public-link']), :style => CSS['newsletter-unsubscribe'], :id => 'newsletter-unsubscribe').html_safe
118 118 end
119 119  
120 120 def read_more(link_address)
... ... @@ -130,13 +130,13 @@ class NewsletterPlugin::Newsletter &lt; ApplicationRecord
130 130 end
131 131  
132 132 def body(data = {})
133   - content_tag(:div, content_tag(:div, message_to_public_link, :style => CSS['newsletter-public-link'])+content_tag(:table,(self.image.nil? ? '' : content_tag(:tr, content_tag(:th, tag(:img, :src => "#{self.environment.top_url}#{self.image.public_filename}", :style => CSS['header-image']),:colspan => 2),:style => CSS['newsletter-header']))+self.posts(data).map do |post|
  133 + content_tag(:div, content_tag(:div, message_to_public_link, :style => CSS['newsletter-public-link']).html_safe+content_tag(:table,(self.image.nil? ? '' : content_tag(:tr, content_tag(:th, tag(:img, :src => "#{self.environment.top_url}#{self.image.public_filename}", :style => CSS['header-image']),:colspan => 2),:style => CSS['newsletter-header'])).html_safe+self.posts(data).map do |post|
134 134 if post.image
135 135 post_with_image(post)
136 136 else
137 137 post_without_image(post)
138 138 end
139   - end.join()+content_tag(:tr, content_tag(:td, self.footer, :colspan => 2)),:style => CSS['breakingnews'])+content_tag(:div,message_to_unsubscribe, :style => CSS['newsletter-unsubscribe']),:style => CSS['breakingnews-wrap'])
  139 + end.join().html_safe+content_tag(:tr, content_tag(:td, self.footer, :colspan => 2)),:style => CSS['breakingnews']).html_safe+content_tag(:div,message_to_unsubscribe, :style => CSS['newsletter-unsubscribe']),:style => CSS['breakingnews-wrap']).html_safe
140 140 end
141 141  
142 142 def default_subject
... ...
plugins/profile_members_headlines/views/blocks/headlines.html.erb
... ... @@ -15,7 +15,7 @@
15 15 <%= show_date(headline.published_at) %>
16 16 </div>
17 17 <div class='tags'>
18   - <%= headline.tags.map { |t| link_to(t, :controller => 'profile', :profile => member.identifier, :action => 'tags', :id => t.name ) }.join("\n") %>
  18 + <%= safe_join(headline.tags.map { |t| link_to(t, :controller => 'profile', :profile => member.identifier, :action => 'tags', :id => t.name ) }, "\n") %>
19 19 </div>
20 20 </div>
21 21 </div>
... ...
plugins/relevant_content/lib/relevant_content_plugin/relevant_content_block.rb
... ... @@ -83,7 +83,7 @@ class RelevantContentPlugin::RelevantContentBlock &lt; Block
83 83 end
84 84 end
85 85 end
86   - return content
  86 + return content.html_safe
87 87 end
88 88  
89 89 def timeout
... ...
plugins/require_auth_to_comment/lib/require_auth_to_comment_plugin.rb
... ... @@ -17,7 +17,7 @@ class RequireAuthToCommentPlugin &lt; Noosfero::Plugin
17 17 end
18 18  
19 19 def profile_editor_extras
20   - expanded_template('profile-editor-extras.html.erb')
  20 + expanded_template('profile-editor-extras.html.erb').html_safe
21 21 end
22 22  
23 23 def stylesheet?
... ...
plugins/site_tour/views/tour_actions.html.erb
... ... @@ -6,11 +6,11 @@
6 6 <script>
7 7 jQuery( document ).ready(function( $ ) {
8 8 <% actions.each_with_index do |action, index| %>
9   - <%= "siteTourPlugin.add('#{j action[:group_name]}', '#{j action[:selector]}', '#{j parse_tour_description(action[:description])}', #{index + 1});" %>
  9 + <%= raw "siteTourPlugin.add('#{j action[:group_name]}', '#{j action[:selector]}', '#{j parse_tour_description(action[:description])}', #{index + 1});" %>
10 10 <% end %>
11 11  
12 12 <% (group_triggers||[]).each do |group| %>
13   - <%= "siteTourPlugin.addGroupTrigger('#{j group[:group_name]}', '#{j group[:selector]}', '#{j group[:event]}');" %>
  13 + <%= "siteTourPlugin.addGroupTrigger('#{j group[:group_name]}', '#{j group[:selector]}', '#{j group[:event]}');".html_safe %>
14 14 <% end %>
15 15  
16 16 siteTourPlugin.setOption('nextLabel', '<%= _('Next') %>');
... ...
plugins/sniffer/views/sniffer_plugin_myprofile/search.html.erb
... ... @@ -46,8 +46,8 @@
46 46 var currentProfile = <%= filter_visible_attr_profile(profile).to_json %>;
47 47 sniffer.search.map.load({
48 48 "zoom": <%= GoogleMaps.initial_zoom.to_json %>,
49   - "balloonUrl": <%= url_for(:controller => :sniffer_plugin_myprofile, :action => :map_balloon, :id => "_id_", :escape => false).to_json %>,
50   - "myBalloonUrl": <%= url_for(:controller => :sniffer_plugin_myprofile, :action => :my_map_balloon, :escape => false).to_json %>,
  49 + "balloonUrl": <%= raw url_for(:controller => :sniffer_plugin_myprofile, :action => :map_balloon, :id => "_id_", :escape => false).to_json %>,
  50 + "myBalloonUrl": <%= raw url_for(:controller => :sniffer_plugin_myprofile, :action => :my_map_balloon, :escape => false).to_json %>,
51 51 "profiles": <%=
52 52 @profiles_data.map do |id, profile_data|
53 53 data = filter_visible_attr_profile(profile_data[:profile])
... ... @@ -55,7 +55,7 @@
55 55 data[:suppliersProducts] = filter_visible_attr_suppliers_products(profile_data[:suppliers_products])
56 56 data[:icon] = profile_data[:profile][:icon]
57 57 data
58   - end.to_json
  58 + end.to_json.html_safe
59 59 %>
60 60 });
61 61 </script>
... ...
public/designs/themes/base/footer.html.erb
... ... @@ -3,7 +3,7 @@
3 3 <%= link_to _('Manual'), '/doc', id: "link-to-doc", class: 'icon-help' %>
4 4 </div><!-- end id="footer-links" -->
5 5 <div id="copyright">
6   - <p><%= _('This social network uses <a href="http://noosfero.org/">Noosfero</a>, developed by %s and licensed under the <a href="http://www.gnu.org/licenses/agpl.html">GNU Affero General Public License</a> version 3 or any later version.') % link_to('Colivre', 'http://colivre.coop.br/') %></p>
  6 + <p><%= (_('This social network uses <a href="http://noosfero.org/">Noosfero</a>, developed by %s and licensed under the <a href="http://www.gnu.org/licenses/agpl.html">GNU Affero General Public License</a> version 3 or any later version.') % link_to('Colivre', 'http://colivre.coop.br/')).html_safe %></p>
7 7 </div><!-- end id="copyright" -->
8 8 <%= language_chooser(environment) %>
9 9 </div>
... ...
public/designs/themes/profile-base/footer.html.erb
1 1 <div id="footer-content">
2   - <p><%= _('This site uses <a href="http://noosfero.org/">Noosfero</a>, developed by %s and licensed under the <a href="http://www.gnu.org/licenses/agpl.html">GNU Affero General Public License</a> version 3 or any later version.') % link_to('Colivre', 'http://colivre.coop.br/') %></p>
  2 + <p><%= _('This site uses <a href="http://noosfero.org/">Noosfero</a>, developed by %s and licensed under the <a href="http://www.gnu.org/licenses/agpl.html">GNU Affero General Public License</a> version 3 or any later version.') % link_to('Colivre', 'http://colivre.coop.br/').html_safe %></p>
3 3 </div>
... ...