Commit ff14fe172e8d7ab85aeb108581bd0a2f7b413307

Authored by Antonio Terceiro
2 parents a831c754 297ad5e9

Merge branch 'stable'

app/helpers/application_helper.rb
@@ -459,7 +459,7 @@ module ApplicationHelper @@ -459,7 +459,7 @@ module ApplicationHelper
459 # #profile_image) or only its name below. 459 # #profile_image) or only its name below.
460 def profile_add_link( profile, image=false, size=:portrait, tag='li') 460 def profile_add_link( profile, image=false, size=:portrait, tag='li')
461 the_class = profile.members.include?(user) ? 'profile_member' : '' 461 the_class = profile.members.include?(user) ? 'profile_member' : ''
462 - name = profile.short_name 462 + name = h(profile.short_name)
463 if image 463 if image
464 display = content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + 464 display = content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) +
465 content_tag( 'span', name, :class => 'org' ) + 465 content_tag( 'span', name, :class => 'org' ) +
@@ -492,7 +492,7 @@ module ApplicationHelper @@ -492,7 +492,7 @@ module ApplicationHelper
492 content_tag tag, 492 content_tag tag,
493 link_to( 493 link_to(
494 content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + 494 content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) +
495 - content_tag( 'span', name, :class => ( profile.class == Person ? 'fn' : 'org' ) ) + 495 + content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) +
496 city + profile_sex_icon( profile ) + profile_cat_icons( profile ), 496 city + profile_sex_icon( profile ) + profile_cat_icons( profile ),
497 profile.url, 497 profile.url,
498 :onclick => 'document.location.href = this.href', # work-arround for ie. 498 :onclick => 'document.location.href = this.href', # work-arround for ie.
@@ -505,7 +505,7 @@ module ApplicationHelper @@ -505,7 +505,7 @@ module ApplicationHelper
505 # displays a link to the community homepage with its image (as generated by 505 # displays a link to the community homepage with its image (as generated by
506 # #profile_image) and its name and number of members beside it. 506 # #profile_image) and its name and number of members beside it.
507 def community_image_link( profile, size=:portrait, tag='li' ) 507 def community_image_link( profile, size=:portrait, tag='li' )
508 - name = profile.name 508 + name = h(profile.name)
509 content_tag tag, 509 content_tag tag,
510 link_to( 510 link_to(
511 content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) + 511 content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) +
app/helpers/content_viewer_helper.rb
@@ -14,7 +14,7 @@ module ContentViewerHelper @@ -14,7 +14,7 @@ module ContentViewerHelper
14 def article_title(article, args = {}) 14 def article_title(article, args = {})
15 title = article.display_title if article.kind_of?(UploadedFile) && article.image? 15 title = article.display_title if article.kind_of?(UploadedFile) && article.image?
16 title = article.title if title.blank? 16 title = article.title if title.blank?
17 - title = content_tag('h1', title, :class => 'title') 17 + title = content_tag('h1', h(title), :class => 'title')
18 if article.belongs_to_blog? 18 if article.belongs_to_blog?
19 unless args[:no_link] 19 unless args[:no_link]
20 title = content_tag('h1', link_to(article.name, article.url), :class => 'title') 20 title = content_tag('h1', link_to(article.name, article.url), :class => 'title')
app/helpers/tags_helper.rb
@@ -57,7 +57,7 @@ module TagsHelper @@ -57,7 +57,7 @@ module TagsHelper
57 display_count = options[:show_count] ? "<small><sup>(#{count})</sup></small>" : "" 57 display_count = options[:show_count] ? "<small><sup>(#{count})</sup></small>" : ""
58 link_to tag + display_count, destination, :style => style 58 link_to tag + display_count, destination, :style => style
59 else 59 else
60 - link_to tag , destination, :style => style, 60 + link_to h(tag) , destination, :style => style,
61 :title => n_( 'one item', '%d items', count ) % count 61 :title => n_( 'one item', '%d items', count ) % count
62 end 62 end
63 63
app/models/article.rb
@@ -348,7 +348,11 @@ class Article &lt; ActiveRecord::Base @@ -348,7 +348,11 @@ class Article &lt; ActiveRecord::Base
348 348
349 def sanitize_tag_list 349 def sanitize_tag_list
350 sanitizer = HTML::FullSanitizer.new 350 sanitizer = HTML::FullSanitizer.new
351 - self.tag_list.names.map!{|i| sanitizer.sanitize(i) } 351 + self.tag_list.names.map!{|i| strip_tag_name sanitizer.sanitize(i) }
  352 + end
  353 +
  354 + def strip_tag_name(tag_name)
  355 + tag_name.gsub(/[<>]/, '')
352 end 356 end
353 357
354 end 358 end
app/models/slideshow_block.rb
@@ -4,13 +4,27 @@ class SlideshowBlock &lt; Block @@ -4,13 +4,27 @@ class SlideshowBlock &lt; Block
4 settings_items :interval, :type => 'integer', :default => 4 4 settings_items :interval, :type => 'integer', :default => 4
5 settings_items :shuffle, :type => 'boolean', :default => false 5 settings_items :shuffle, :type => 'boolean', :default => false
6 settings_items :navigation, :type => 'boolean', :default => false 6 settings_items :navigation, :type => 'boolean', :default => false
  7 + settings_items :image_size, :type => 'string', :default => 'thumb'
7 8
8 def self.description 9 def self.description
9 _('Slideshow') 10 _('Slideshow')
10 end 11 end
11 12
12 def gallery 13 def gallery
13 - gallery_id ? Folder.find(gallery_id) : nil 14 + gallery_id ? Folder.find(:first, :conditions => { :id => gallery_id }) : nil
  15 + end
  16 +
  17 + def public_filename_for(image)
  18 + check_filename(image, image_size) || check_filename(image, 'thumb')
  19 + end
  20 +
  21 + def check_filename(image, size)
  22 + filename = image.public_filename(size)
  23 + if File.exists?(File.join(Rails.root, 'public', filename))
  24 + filename
  25 + else
  26 + nil
  27 + end
14 end 28 end
15 29
16 def block_images 30 def block_images
app/models/uploaded_file.rb
@@ -21,7 +21,7 @@ class UploadedFile &lt; Article @@ -21,7 +21,7 @@ class UploadedFile &lt; Article
21 # :min_size => 2.megabytes 21 # :min_size => 2.megabytes
22 # :max_size => 5.megabytes 22 # :max_size => 5.megabytes
23 has_attachment :storage => :file_system, 23 has_attachment :storage => :file_system,
24 - :thumbnails => { :icon => [24,24], :thumb => '130x130>', :display => '640X480>' }, 24 + :thumbnails => { :icon => [24,24], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' },
25 :thumbnail_class => Thumbnail, 25 :thumbnail_class => Thumbnail,
26 :max_size => 5.megabytes # remember to update validate message below 26 :max_size => 5.megabytes # remember to update validate message below
27 27
app/views/blocks/profile_image.rhtml
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 </div> 11 </div>
12 12
13 <% if show_name %> 13 <% if show_name %>
14 - <p><%= block.owner.short_name %></p> 14 + <p><%= h block.owner.short_name %></p>
15 <% end %> 15 <% end %>
16 16
17 <% if !user.nil? and user.has_permission?('edit_profile', profile) %> 17 <% if !user.nil? and user.has_permission?('edit_profile', profile) %>
app/views/blocks/profile_info.rhtml
1 <div class="vcard"> 1 <div class="vcard">
2 2
3 -<h2 class="<%= profile.class == Person ? 'fn' : 'org' %>"><%= block.owner.short_name %></h2> 3 +<h2 class="<%= profile.class == Person ? 'fn' : 'org' %>"><%= h block.owner.short_name %></h2>
4 4
5 <div class="profile-info-picture"> 5 <div class="profile-info-picture">
6 <div class="profile-info-picture-inner1"> 6 <div class="profile-info-picture-inner1">
app/views/blocks/slideshow.rhtml
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <div class='slideshow-container'> 5 <div class='slideshow-container'>
6 <% images.each do |img| %> 6 <% images.each do |img| %>
7 <a href="<%= url_for(img.external_link.blank? ? img.view_url: img.external_link) %>"> 7 <a href="<%= url_for(img.external_link.blank? ? img.view_url: img.external_link) %>">
8 - <%= content_tag('div', '', :style => "background-image: url(#{img.public_filename(:thumb)})", :title => (img.abstract.blank? ? '' : img.abstract)) %> 8 + <%= content_tag('div', '', :style => "background-image: url(#{block.public_filename_for(img)})", :title => (img.abstract.blank? ? '' : img.abstract)) %>
9 <% if !img.abstract.blank? %> 9 <% if !img.abstract.blank? %>
10 <span class='image-description'><%= img.abstract %></span> 10 <span class='image-description'><%= img.abstract %></span>
11 <% end %> 11 <% end %>
app/views/box_organizer/_slideshow_block.rhtml
@@ -3,6 +3,8 @@ @@ -3,6 +3,8 @@
3 [ _('%{gallery} (%{count} images)') % {:gallery => item.path, :count => item.images.reject{|image| image.folder?}.count}, item.id ] 3 [ _('%{gallery} (%{count} images)') % {:gallery => item.path, :count => item.images.reject{|image| image.folder?}.count}, item.id ]
4 }) %> 4 }) %>
5 5
  6 +<%= labelled_form_field(_('Image size'), select('block', 'image_size', [[_('Miniatura'), 'thumb'],[_('Slideshow size'), 'slideshow']])) %>
  7 +
6 <%= labelled_form_field _('Image transition:'), select('block', 'interval', [[_('No automatic transition'), 0]] + [1, 2, 3, 4, 5, 10, 20, 30, 60].map {|item| [n_('Every 1 second', 'Every %d seconds', item) % item, item]}) %> 8 <%= labelled_form_field _('Image transition:'), select('block', 'interval', [[_('No automatic transition'), 0]] + [1, 2, 3, 4, 5, 10, 20, 30, 60].map {|item| [n_('Every 1 second', 'Every %d seconds', item) % item, item]}) %>
7 9
8 <%= labelled_form_field check_box(:block, :shuffle) + _('Show images in random order'), '' %> 10 <%= labelled_form_field check_box(:block, :shuffle) + _('Show images in random order'), '' %>
app/views/cms/_tiny_mce_article.rhtml
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 2
3 <%= render :file => 'shared/tiny_mce' %> 3 <%= render :file => 'shared/tiny_mce' %>
4 4
5 -<div style='margin-left: 20px;'> 5 +<div>
6 <% if profile.enterprise? && environment.enabled?('disable_cms') && !@article.name.blank? %> 6 <% if profile.enterprise? && environment.enabled?('disable_cms') && !@article.name.blank? %>
7 <div> 7 <div>
8 <%= _('Title') %>: <%= @article.name %> 8 <%= _('Title') %>: <%= @article.name %>
app/views/cms/publish.rhtml
@@ -14,16 +14,24 @@ @@ -14,16 +14,24 @@
14 </div> 14 </div>
15 <% end %> 15 <% end %>
16 16
17 -<% form_tag do%>  
18 - <%= hidden_field_tag :back_to, @back_to %>  
19 - <% @groups.each do |group| %>  
20 - <%= labelled_check_box group.name, 'marked_groups[][group_id]', group.id, @marked_groups.include?(group) %><br />  
21 - <%= labelled_text_field _('Title') + ': ', 'marked_groups[][name]', @article.name, :style => 'width: 100%' %>  
22 - <hr />  
23 - <% end %>  
24 17
25 - <% button_bar do %>  
26 - <%= submit_button 'spread', _('Publish') %> 18 +<!-- Workaroud while the publish feature isn't ready for Events -->
  19 +<% unless @article.is_a?(Event) %>
  20 + <% form_tag do%>
  21 + <%= hidden_field_tag :back_to, @back_to %>
  22 + <% @groups.each do |group| %>
  23 + <%= labelled_check_box group.name, 'marked_groups[][group_id]', group.id, @marked_groups.include?(group) %><br />
  24 + <%= labelled_text_field _('Title') + ': ', 'marked_groups[][name]', @article.name, :style => 'width: 100%' %>
  25 + <hr />
  26 + <% end %>
  27 +
  28 + <% button_bar do %>
  29 + <%= submit_button 'spread', _('Publish') %>
  30 + <% end %>
27 <% end %> 31 <% end %>
  32 +<% else %>
  33 + <div class='atention'>
  34 + <%= _("This option is temporarily disabled.") %>
  35 + </div>
28 <% end %> 36 <% end %>
29 37
app/views/cms/upload_files.rhtml
@@ -20,5 +20,5 @@ @@ -20,5 +20,5 @@
20 <h5><%= _('Uploading files to %s') % content_tag('code', @target) %></h5> 20 <h5><%= _('Uploading files to %s') % content_tag('code', @target) %></h5>
21 21
22 <% form_for('uploaded_file', :url => { :action => 'upload_files' }, :html => {:multipart => true}) do |f| %> 22 <% form_for('uploaded_file', :url => { :action => 'upload_files' }, :html => {:multipart => true}) do |f| %>
23 - <%= render :partial => 'upload_file_form', :locals => { :size => '50'} %> 23 + <%= render :partial => 'upload_file_form', :locals => { :size => '45'} %>
24 <% end %> 24 <% end %>
app/views/layouts/application-ng.rhtml
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= html_language %>" lang="<%= html_language %>"> 2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= html_language %>" lang="<%= html_language %>">
3 <head> 3 <head>
4 - <title><%= page_title %></title> 4 + <title><%= h page_title %></title>
5 <%= meta_tags_for_article(@page) %> 5 <%= meta_tags_for_article(@page) %>
6 <!--<meta http-equiv="refresh" content="1"/>--> 6 <!--<meta http-equiv="refresh" content="1"/>-->
7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
app/views/layouts/application.rhtml
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= html_language %>" lang="<%= html_language %>"> 2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= html_language %>" lang="<%= html_language %>">
3 <head> 3 <head>
4 - <title><%= page_title %></title> 4 + <title><%= h page_title %></title>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6 <meta name="description" content="<%= @environment.name %>" /> 6 <meta name="description" content="<%= @environment.name %>" />
7 <meta name="keywords" content="Noosfero, Community, Open Source" /> 7 <meta name="keywords" content="Noosfero, Community, Open Source" />
app/views/layouts/slideshow.rhtml
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 %></title> 11 %></title>
12 12
13 <%= stylesheet_import "slideshow" %> 13 <%= stylesheet_import "slideshow" %>
14 - <%= javascript_include_tag 'sliderjs', 'pikachoose', :cache => 'cache-slideshow' %> 14 + <%= javascript_include_tag 'jquery-latest', 'sliderjs', 'pikachoose', :cache => 'cache-slideshow' %>
15 <script type="text/javascript"> 15 <script type="text/javascript">
16 $(document).ready(function (){ 16 $(document).ready(function (){
17 $("#slideshow").PikaChoose({ 17 $("#slideshow").PikaChoose({
app/views/profile/index.rhtml
1 <%= render :partial => 'shared/disabled_enterprise' %> 1 <%= render :partial => 'shared/disabled_enterprise' %>
2 2
3 -<h1><%= profile.name %></h1> 3 +<h1><%= h profile.name %></h1>
4 4
5 <% if @action %> 5 <% if @action %>
6 <%= render :partial => 'private_profile' %> 6 <%= render :partial => 'private_profile' %>
app/views/profile_editor/index.rhtml
1 <div id="profile-editor-index"> 1 <div id="profile-editor-index">
2 2
3 <h1 class="block-title"> 3 <h1 class="block-title">
4 - <span class='control-panel-title'><%= profile.short_name %></span> 4 + <span class='control-panel-title'><%= h profile.short_name %></span>
5 <span class='control-panel-sep'>&#150;</span> 5 <span class='control-panel-sep'>&#150;</span>
6 <span class='control-panel-subtitle'><%= _('Control Panel') %></span> 6 <span class='control-panel-subtitle'><%= _('Control Panel') %></span>
7 </h1> 7 </h1>
db/migrate/20100413231206_strip_html_from_tag_names.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +class StripHtmlFromTagNames < ActiveRecord::Migration
  2 + def self.up
  3 + Tag.all(:conditions => "name LIKE '%<%' OR name LIKE '%>%'").each do |tag|
  4 + tag.name = tag.name.gsub(/[<>]/, '')
  5 + tag.save
  6 + end
  7 + end
  8 +
  9 + def self.down
  10 + say "WARNING: cannot undo this migration"
  11 + end
  12 +end
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 # 9 #
10 # It's strongly recommended to check this file into your version control system. 10 # It's strongly recommended to check this file into your version control system.
11 11
12 -ActiveRecord::Schema.define(:version => 20100326171758) do 12 +ActiveRecord::Schema.define(:version => 20100413231206) do
13 13
14 create_table "article_versions", :force => true do |t| 14 create_table "article_versions", :force => true do |t|
15 t.integer "article_id" 15 t.integer "article_id"
public/stylesheets/application.css
@@ -2536,7 +2536,7 @@ div#activation_enterprise div { @@ -2536,7 +2536,7 @@ div#activation_enterprise div {
2536 width: 40%; 2536 width: 40%;
2537 height: 630px; 2537 height: 630px;
2538 border: none; 2538 border: none;
2539 - margin: 115px 20px 0px 0px; 2539 + margin: 104px 20px 0px 0px;
2540 padding: 0px; 2540 padding: 0px;
2541 overflow: hidden; 2541 overflow: hidden;
2542 } 2542 }
@@ -2546,12 +2546,11 @@ div#activation_enterprise div { @@ -2546,12 +2546,11 @@ div#activation_enterprise div {
2546 } 2546 }
2547 2547
2548 .controller-cms div.with_media_panel { 2548 .controller-cms div.with_media_panel {
2549 - width: 57%;  
2550 float: left; 2549 float: left;
2551 } 2550 }
2552 -.controller-cms div.no_media_panel {  
2553 - margin-left: 200px;  
2554 - margin-right: 200px; 2551 +
  2552 +div.with_media_panel .formfield input {
  2553 + width: 100%;
2555 } 2554 }
2556 2555
2557 /* ==> public/stylesheets/controller_contact.css <== */ 2556 /* ==> public/stylesheets/controller_contact.css <== */
test/unit/article_test.rb
@@ -842,4 +842,21 @@ class ArticleTest &lt; Test::Unit::TestCase @@ -842,4 +842,21 @@ class ArticleTest &lt; Test::Unit::TestCase
842 842
843 assert_equal [ published ], profile.articles.published 843 assert_equal [ published ], profile.articles.published
844 end 844 end
  845 +
  846 + should 'sanitize tags after save article' do
  847 + article = fast_create(Article, :slug => 'article-with-tags', :profile_id => profile.id)
  848 + article.tags << Tag.new(:name => "TV Web w<script type='javascript'></script>")
  849 + assert_match /[<>]/, article.tags.last.name
  850 + article.save!
  851 + assert_no_match /[<>]/, article.tags.last.name
  852 + end
  853 +
  854 + should 'strip HTML from tag names after save article' do
  855 + article = fast_create(Article, :slug => 'article-with-tags', :profile_id => profile.id)
  856 + article.tags << Tag.new(:name => "TV Web w<script type=...")
  857 + assert_match /</, article.tags.last.name
  858 + article.save!
  859 + assert_no_match /</, article.tags.last.name
  860 + end
  861 +
845 end 862 end
test/unit/slideshow_block_test.rb
@@ -15,6 +15,10 @@ class SlideshowBlockTest &lt; ActiveSupport::TestCase @@ -15,6 +15,10 @@ class SlideshowBlockTest &lt; ActiveSupport::TestCase
15 assert_equal gallery, slideshow_block.gallery 15 assert_equal gallery, slideshow_block.gallery
16 end 16 end
17 17
  18 + should 'not crash if referencing unexisting folder' do
  19 + assert_nil SlideshowBlock.new(:gallery_id => -999).gallery
  20 + end
  21 +
18 should 'default interval between transitions is 4 seconds' do 22 should 'default interval between transitions is 4 seconds' do
19 slideshow = SlideshowBlock.new 23 slideshow = SlideshowBlock.new
20 assert_equal 4, slideshow.interval 24 assert_equal 4, slideshow.interval
@@ -61,4 +65,36 @@ class SlideshowBlockTest &lt; ActiveSupport::TestCase @@ -61,4 +65,36 @@ class SlideshowBlockTest &lt; ActiveSupport::TestCase
61 assert_not_includes block.block_images, folder 65 assert_not_includes block.block_images, folder
62 end 66 end
63 67
  68 + should 'display "thumb" size by default' do
  69 + assert_equal 'thumb', SlideshowBlock.new.image_size
  70 + end
  71 +
  72 + should 'set different image size' do
  73 + block = SlideshowBlock.new(:image_size => 'slideshow')
  74 + assert_equal 'slideshow', block.image_size
  75 + end
  76 +
  77 + should 'decide correct public filename for image' do
  78 + image = mock
  79 + image.expects(:public_filename).with('slideshow').returns('/bli/slideshow.png')
  80 + File.expects(:exists?).with("#{Rails.root}/public/bli/slideshow.png").returns(true)
  81 +
  82 + assert_equal '/bli/slideshow.png', SlideshowBlock.new(:image_size => 'slideshow').public_filename_for(image)
  83 + end
  84 +
  85 + should 'fallback to existing size in case the requested size does not exist' do
  86 + block = SlideshowBlock.new(:image_size => 'slideshow')
  87 +
  88 + image = mock
  89 + # "slideshow" size does not exist
  90 + image.expects(:public_filename).with('slideshow').returns('/bli/slideshow.png')
  91 + File.expects(:exists?).with("#{Rails.root}/public/bli/slideshow.png").returns(false) # <<<<<
  92 +
  93 + # thumb size does exist
  94 + image.expects(:public_filename).with('thumb').returns('/bli/thumb.png')
  95 + File.expects(:exists?).with("#{Rails.root}/public/bli/thumb.png").returns(true) # <<<<<
  96 +
  97 + assert_equal '/bli/thumb.png', block.public_filename_for(image)
  98 + end
  99 +
64 end 100 end