Commit ff14fe172e8d7ab85aeb108581bd0a2f7b413307
Exists in
master
and in
29 other branches
Merge branch 'stable'
Showing
23 changed files
with
125 additions
and
33 deletions
Show diff stats
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 < 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 < 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 < 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
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
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
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'>–</span> |
6 | 6 | <span class='control-panel-subtitle'><%= _('Control Panel') %></span> |
7 | 7 | </h1> | ... | ... |
... | ... | @@ -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 < 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 < 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 < 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 | ... | ... |