##// END OF EJS Templates
Appends the filename to the attachment url so that clients that ignore content-disposition http header get the real filename (#1649)....
Jean-Philippe Lang -
r1669:9b579de9e234
parent child
Show More
@@ -43,6 +43,9 class AttachmentsController < ApplicationController
43 private
43 private
44 def find_project
44 def find_project
45 @attachment = Attachment.find(params[:id])
45 @attachment = Attachment.find(params[:id])
46 # Show 404 if the filename in the url is wrong
47 raise ActiveRecord::RecordNotFound if params[:filename] && params[:filename] != @attachment.filename
48
46 @project = @attachment.project
49 @project = @attachment.project
47 permission = @attachment.container.is_a?(Version) ? :view_files : "view_#{@attachment.container.class.name.underscore.pluralize}".to_sym
50 permission = @attachment.container.is_a?(Version) ? :view_files : "view_#{@attachment.container.class.name.underscore.pluralize}".to_sym
48 allowed = User.current.allowed_to?(permission, @project)
51 allowed = User.current.allowed_to?(permission, @project)
@@ -47,6 +47,17 module ApplicationHelper
47 link_to "#{issue.tracker.name} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue}, options
47 link_to "#{issue.tracker.name} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue}, options
48 end
48 end
49
49
50 # Generates a link to an attachment.
51 # Options:
52 # * :text - Link text (default to attachment filename)
53 # * :download - Force download (default: false)
54 def link_to_attachment(attachment, options={})
55 text = options.delete(:text) || attachment.filename
56 action = options.delete(:download) ? 'download' : 'show'
57
58 link_to(h(text), {:controller => 'attachments', :action => action, :id => attachment, :filename => attachment.filename }, options)
59 end
60
50 def toggle_link(name, id, options={})
61 def toggle_link(name, id, options={})
51 onclick = "Element.toggle('#{id}'); "
62 onclick = "Element.toggle('#{id}'); "
52 onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
63 onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
@@ -95,9 +95,9 module IssuesHelper
95 label = content_tag('strong', label)
95 label = content_tag('strong', label)
96 old_value = content_tag("i", h(old_value)) if detail.old_value
96 old_value = content_tag("i", h(old_value)) if detail.old_value
97 old_value = content_tag("strike", old_value) if detail.old_value and (!detail.value or detail.value.empty?)
97 old_value = content_tag("strike", old_value) if detail.old_value and (!detail.value or detail.value.empty?)
98 if detail.property == 'attachment' && !value.blank? && Attachment.find_by_id(detail.prop_key)
98 if detail.property == 'attachment' && !value.blank? && a = Attachment.find_by_id(detail.prop_key)
99 # Link to the attachment if it has not been removed
99 # Link to the attachment if it has not been removed
100 value = link_to(value, :controller => 'attachments', :action => 'show', :id => detail.prop_key)
100 value = link_to_attachment(a)
101 else
101 else
102 value = content_tag("i", h(value)) if value
102 value = content_tag("i", h(value)) if value
103 end
103 end
@@ -26,7 +26,7 class Attachment < ActiveRecord::Base
26 validates_length_of :disk_filename, :maximum => 255
26 validates_length_of :disk_filename, :maximum => 255
27
27
28 acts_as_event :title => :filename,
28 acts_as_event :title => :filename,
29 :url => Proc.new {|o| {:controller => 'attachments', :action => 'download', :id => o.id}}
29 :url => Proc.new {|o| {:controller => 'attachments', :action => 'download', :id => o.id, :filename => o.filename}}
30
30
31 cattr_accessor :storage_path
31 cattr_accessor :storage_path
32 @@storage_path = "#{RAILS_ROOT}/files"
32 @@storage_path = "#{RAILS_ROOT}/files"
@@ -1,6 +1,6
1 <div class="attachments">
1 <div class="attachments">
2 <% for attachment in attachments %>
2 <% for attachment in attachments %>
3 <p><%= link_to attachment.filename, {:controller => 'attachments', :action => 'show', :id => attachment }, :class => 'icon icon-attachment' -%>
3 <p><%= link_to_attachment attachment, :class => 'icon icon-attachment' -%>
4 <%= h(" - #{attachment.description}") unless attachment.description.blank? %>
4 <%= h(" - #{attachment.description}") unless attachment.description.blank? %>
5 <span class="size">(<%= number_to_human_size attachment.filesize %>)</span>
5 <span class="size">(<%= number_to_human_size attachment.filesize %>)</span>
6 <% if options[:delete_url] %>
6 <% if options[:delete_url] %>
@@ -3,7 +3,7
3 <div class="attachments">
3 <div class="attachments">
4 <p><%= h("#{@attachment.description} - ") unless @attachment.description.blank? %>
4 <p><%= h("#{@attachment.description} - ") unless @attachment.description.blank? %>
5 <span class="author"><%= @attachment.author %>, <%= format_time(@attachment.created_on) %></span></p>
5 <span class="author"><%= @attachment.author %>, <%= format_time(@attachment.created_on) %></span></p>
6 <p><%= link_to l(:button_download), {:controller => 'attachments', :action => 'download', :id => @attachment } -%>
6 <p><%= link_to_attachment @attachment, :text => l(:button_download), :download => true -%>
7 <span class="size">(<%= number_to_human_size @attachment.filesize %>)</span></p>
7 <span class="size">(<%= number_to_human_size @attachment.filesize %>)</span></p>
8
8
9 </div>
9 </div>
@@ -3,7 +3,7
3 <div class="attachments">
3 <div class="attachments">
4 <p><%= h("#{@attachment.description} - ") unless @attachment.description.blank? %>
4 <p><%= h("#{@attachment.description} - ") unless @attachment.description.blank? %>
5 <span class="author"><%= @attachment.author %>, <%= format_time(@attachment.created_on) %></span></p>
5 <span class="author"><%= @attachment.author %>, <%= format_time(@attachment.created_on) %></span></p>
6 <p><%= link_to l(:button_download), {:controller => 'attachments', :action => 'download', :id => @attachment } -%>
6 <p><%= link_to_attachment @attachment, :text => l(:button_download), :download => true -%>
7 <span class="size">(<%= number_to_human_size @attachment.filesize %>)</span></p>
7 <span class="size">(<%= number_to_human_size @attachment.filesize %>)</span></p>
8
8
9 </div>
9 </div>
@@ -23,8 +23,7
23 <% for file in version.attachments %>
23 <% for file in version.attachments %>
24 <tr class="<%= cycle("odd", "even") %>">
24 <tr class="<%= cycle("odd", "even") %>">
25 <td></td>
25 <td></td>
26 <td><%= link_to(h(file.filename), {:controller => 'attachments', :action => 'download', :id => file},
26 <td><%= link_to_attachment file, :download => true, :title => file.description %></td>
27 :title => file.description) %></td>
28 <td align="center"><%= format_time(file.created_on) %></td>
27 <td align="center"><%= format_time(file.created_on) %></td>
29 <td align="center"><%= number_to_human_size(file.filesize) %></td>
28 <td align="center"><%= number_to_human_size(file.filesize) %></td>
30 <td align="center"><%= file.downloads %></td>
29 <td align="center"><%= file.downloads %></td>
@@ -32,8 +32,10 ActionController::Routing::Routes.draw do |map|
32 omap.repositories_revision 'repositories/revision/:id/:rev', :action => 'revision'
32 omap.repositories_revision 'repositories/revision/:id/:rev', :action => 'revision'
33 end
33 end
34
34
35 map.connect 'attachments/:id', :controller => 'attachments', :action => 'show'
35 map.connect 'attachments/:id', :controller => 'attachments', :action => 'show', :id => /\d+/
36
36 map.connect 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/
37 map.connect 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/
38
37 # Allow downloading Web Service WSDL as a file with an extension
39 # Allow downloading Web Service WSDL as a file with an extension
38 # instead of a file named 'wsdl'
40 # instead of a file named 'wsdl'
39 map.connect ':controller/service.wsdl', :action => 'wsdl'
41 map.connect ':controller/service.wsdl', :action => 'wsdl'
@@ -33,6 +33,21 class AttachmentsControllerTest < Test::Unit::TestCase
33 User.current = nil
33 User.current = nil
34 end
34 end
35
35
36 def test_routing
37 assert_routing('/attachments/1', :controller => 'attachments', :action => 'show', :id => '1')
38 assert_routing('/attachments/1/filename.ext', :controller => 'attachments', :action => 'show', :id => '1', :filename => 'filename.ext')
39 assert_routing('/attachments/download/1', :controller => 'attachments', :action => 'download', :id => '1')
40 assert_routing('/attachments/download/1/filename.ext', :controller => 'attachments', :action => 'download', :id => '1', :filename => 'filename.ext')
41 end
42
43 def test_recognizes
44 assert_recognizes({:controller => 'attachments', :action => 'show', :id => '1'}, '/attachments/1')
45 assert_recognizes({:controller => 'attachments', :action => 'show', :id => '1'}, '/attachments/show/1')
46 assert_recognizes({:controller => 'attachments', :action => 'show', :id => '1', :filename => 'filename.ext'}, '/attachments/1/filename.ext')
47 assert_recognizes({:controller => 'attachments', :action => 'download', :id => '1'}, '/attachments/download/1')
48 assert_recognizes({:controller => 'attachments', :action => 'download', :id => '1', :filename => 'filename.ext'},'/attachments/download/1/filename.ext')
49 end
50
36 def test_show_diff
51 def test_show_diff
37 get :show, :id => 5
52 get :show, :id => 5
38 assert_response :success
53 assert_response :success
General Comments 0
You need to be logged in to leave comments. Login now