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 459 # #profile_image) or only its name below.
460 460 def profile_add_link( profile, image=false, size=:portrait, tag='li')
461 461 the_class = profile.members.include?(user) ? 'profile_member' : ''
462   - name = profile.short_name
  462 + name = h(profile.short_name)
463 463 if image
464 464 display = content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) +
465 465 content_tag( 'span', name, :class => 'org' ) +
... ... @@ -492,7 +492,7 @@ module ApplicationHelper
492 492 content_tag tag,
493 493 link_to(
494 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 496 city + profile_sex_icon( profile ) + profile_cat_icons( profile ),
497 497 profile.url,
498 498 :onclick => 'document.location.href = this.href', # work-arround for ie.
... ... @@ -505,7 +505,7 @@ module ApplicationHelper
505 505 # displays a link to the community homepage with its image (as generated by
506 506 # #profile_image) and its name and number of members beside it.
507 507 def community_image_link( profile, size=:portrait, tag='li' )
508   - name = profile.name
  508 + name = h(profile.name)
509 509 content_tag tag,
510 510 link_to(
511 511 content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) +
... ...
app/helpers/content_viewer_helper.rb
... ... @@ -14,7 +14,7 @@ module ContentViewerHelper
14 14 def article_title(article, args = {})
15 15 title = article.display_title if article.kind_of?(UploadedFile) && article.image?
16 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 18 if article.belongs_to_blog?
19 19 unless args[:no_link]
20 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 57 display_count = options[:show_count] ? "<small><sup>(#{count})</sup></small>" : ""
58 58 link_to tag + display_count, destination, :style => style
59 59 else
60   - link_to tag , destination, :style => style,
  60 + link_to h(tag) , destination, :style => style,
61 61 :title => n_( 'one item', '%d items', count ) % count
62 62 end
63 63  
... ...
app/models/article.rb
... ... @@ -348,7 +348,11 @@ class Article &lt; ActiveRecord::Base
348 348  
349 349 def sanitize_tag_list
350 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 356 end
353 357  
354 358 end
... ...
app/models/slideshow_block.rb
... ... @@ -4,13 +4,27 @@ class SlideshowBlock &lt; Block
4 4 settings_items :interval, :type => 'integer', :default => 4
5 5 settings_items :shuffle, :type => 'boolean', :default => false
6 6 settings_items :navigation, :type => 'boolean', :default => false
  7 + settings_items :image_size, :type => 'string', :default => 'thumb'
7 8  
8 9 def self.description
9 10 _('Slideshow')
10 11 end
11 12  
12 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 28 end
15 29  
16 30 def block_images
... ...
app/models/uploaded_file.rb
... ... @@ -21,7 +21,7 @@ class UploadedFile &lt; Article
21 21 # :min_size => 2.megabytes
22 22 # :max_size => 5.megabytes
23 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 25 :thumbnail_class => Thumbnail,
26 26 :max_size => 5.megabytes # remember to update validate message below
27 27  
... ...
app/views/blocks/profile_image.rhtml
... ... @@ -11,7 +11,7 @@
11 11 </div>
12 12  
13 13 <% if show_name %>
14   - <p><%= block.owner.short_name %></p>
  14 + <p><%= h block.owner.short_name %></p>
15 15 <% end %>
16 16  
17 17 <% if !user.nil? and user.has_permission?('edit_profile', profile) %>
... ...
app/views/blocks/profile_info.rhtml
1 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 5 <div class="profile-info-picture">
6 6 <div class="profile-info-picture-inner1">
... ...
app/views/blocks/slideshow.rhtml
... ... @@ -5,7 +5,7 @@
5 5 <div class='slideshow-container'>
6 6 <% images.each do |img| %>
7 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 9 <% if !img.abstract.blank? %>
10 10 <span class='image-description'><%= img.abstract %></span>
11 11 <% end %>
... ...
app/views/box_organizer/_slideshow_block.rhtml
... ... @@ -3,6 +3,8 @@
3 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 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 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 2  
3 3 <%= render :file => 'shared/tiny_mce' %>
4 4  
5   -<div style='margin-left: 20px;'>
  5 +<div>
6 6 <% if profile.enterprise? && environment.enabled?('disable_cms') && !@article.name.blank? %>
7 7 <div>
8 8 <%= _('Title') %>: <%= @article.name %>
... ...
app/views/cms/publish.rhtml
... ... @@ -14,16 +14,24 @@
14 14 </div>
15 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 31 <% end %>
  32 +<% else %>
  33 + <div class='atention'>
  34 + <%= _("This option is temporarily disabled.") %>
  35 + </div>
28 36 <% end %>
29 37  
... ...
app/views/cms/upload_files.rhtml
... ... @@ -20,5 +20,5 @@
20 20 <h5><%= _('Uploading files to %s') % content_tag('code', @target) %></h5>
21 21  
22 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 24 <% end %>
... ...
app/views/layouts/application-ng.rhtml
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 %>">
3 3 <head>
4   - <title><%= page_title %></title>
  4 + <title><%= h page_title %></title>
5 5 <%= meta_tags_for_article(@page) %>
6 6 <!--<meta http-equiv="refresh" content="1"/>-->
7 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
... ...
app/views/layouts/application.rhtml
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 %>">
3 3 <head>
4   - <title><%= page_title %></title>
  4 + <title><%= h page_title %></title>
5 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6 6 <meta name="description" content="<%= @environment.name %>" />
7 7 <meta name="keywords" content="Noosfero, Community, Open Source" />
... ...
app/views/layouts/slideshow.rhtml
... ... @@ -11,7 +11,7 @@
11 11 %></title>
12 12  
13 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 15 <script type="text/javascript">
16 16 $(document).ready(function (){
17 17 $("#slideshow").PikaChoose({
... ...
app/views/profile/index.rhtml
1 1 <%= render :partial => 'shared/disabled_enterprise' %>
2 2  
3   -<h1><%= profile.name %></h1>
  3 +<h1><%= h profile.name %></h1>
4 4  
5 5 <% if @action %>
6 6 <%= render :partial => 'private_profile' %>
... ...
app/views/profile_editor/index.rhtml
1 1 <div id="profile-editor-index">
2 2  
3 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 5 <span class='control-panel-sep'>&#150;</span>
6 6 <span class='control-panel-subtitle'><%= _('Control Panel') %></span>
7 7 </h1>
... ...
db/migrate/20100413231206_strip_html_from_tag_names.rb 0 → 100644
... ... @@ -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
... ...
db/schema.rb
... ... @@ -9,7 +9,7 @@
9 9 #
10 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 14 create_table "article_versions", :force => true do |t|
15 15 t.integer "article_id"
... ...
public/stylesheets/application.css
... ... @@ -2536,7 +2536,7 @@ div#activation_enterprise div {
2536 2536 width: 40%;
2537 2537 height: 630px;
2538 2538 border: none;
2539   - margin: 115px 20px 0px 0px;
  2539 + margin: 104px 20px 0px 0px;
2540 2540 padding: 0px;
2541 2541 overflow: hidden;
2542 2542 }
... ... @@ -2546,12 +2546,11 @@ div#activation_enterprise div {
2546 2546 }
2547 2547  
2548 2548 .controller-cms div.with_media_panel {
2549   - width: 57%;
2550 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 2556 /* ==> public/stylesheets/controller_contact.css <== */
... ...
test/unit/article_test.rb
... ... @@ -842,4 +842,21 @@ class ArticleTest &lt; Test::Unit::TestCase
842 842  
843 843 assert_equal [ published ], profile.articles.published
844 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 862 end
... ...
test/unit/slideshow_block_test.rb
... ... @@ -15,6 +15,10 @@ class SlideshowBlockTest &lt; ActiveSupport::TestCase
15 15 assert_equal gallery, slideshow_block.gallery
16 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 22 should 'default interval between transitions is 4 seconds' do
19 23 slideshow = SlideshowBlock.new
20 24 assert_equal 4, slideshow.interval
... ... @@ -61,4 +65,36 @@ class SlideshowBlockTest &lt; ActiveSupport::TestCase
61 65 assert_not_includes block.block_images, folder
62 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 100 end
... ...