From 6475a4d3a3bef0a553b844b13068b077e78f3146 Mon Sep 17 00:00:00 2001 From: Braulio Bhavamitra Date: Wed, 16 Oct 2013 14:30:58 -0300 Subject: [PATCH] Force a browser to save file as after clicking a uploaded file link --- app/controllers/public/content_viewer_controller.rb | 5 +++-- app/models/article.rb | 14 ++++++++++++-- app/models/uploaded_file.rb | 6 ++++++ test/fixtures/files/500.html | 1 + test/functional/content_viewer_controller_test.rb | 16 ++++++++++++++-- 5 files changed, 36 insertions(+), 6 deletions(-) create mode 120000 test/fixtures/files/500.html diff --git a/app/controllers/public/content_viewer_controller.rb b/app/controllers/public/content_viewer_controller.rb index 519d006..3cd93b6 100644 --- a/app/controllers/public/content_viewer_controller.rb +++ b/app/controllers/public/content_viewer_controller.rb @@ -53,8 +53,9 @@ class ContentViewerController < ApplicationController # At this point the page will be showed @page.hit - unless @page.mime_type == 'text/html' || (@page.image? && params[:view]) + if @page.download? params[:view] headers['Content-Type'] = @page.mime_type + headers.merge! @page.download_headers data = @page.data # TODO test the condition @@ -70,7 +71,7 @@ class ContentViewerController < ApplicationController #FIXME see a better way to do this. It's not need to pass this variable anymore @comment = Comment.new - + if @page.has_posts? posts = if params[:year] and params[:month] filter_date = DateTime.parse("#{params[:year]}-#{params[:month]}-01") diff --git a/app/models/article.rb b/app/models/article.rb index 4f564d8..aacffe0 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -188,7 +188,7 @@ class Article < ActiveRecord::Base pending_categorizations.clear end - acts_as_taggable + acts_as_taggable N_('Tag list') acts_as_filesystem @@ -268,7 +268,7 @@ class Article < ActiveRecord::Base end # returns the data of the article. Must be overriden in each subclass to - # provide the correct content for the article. + # provide the correct content for the article. def data body end @@ -360,6 +360,16 @@ class Article < ActiveRecord::Base false end + def download? view = nil + (self.uploaded_file? and not self.image?) or + (self.image? and view.blank?) or + (not self.uploaded_file? and self.mime_type != 'text/html') + end + + def download_headers + {} + end + named_scope :native_translations, :conditions => { :translation_of_id => nil } def translatable? diff --git a/app/models/uploaded_file.rb b/app/models/uploaded_file.rb index 5be009e..3d7825d 100644 --- a/app/models/uploaded_file.rb +++ b/app/models/uploaded_file.rb @@ -86,6 +86,12 @@ class UploadedFile < Article self.name = self.filename end + def download_headers + { + 'Content-Disposition' => "attachment; filename=\"#{self.filename}\"", + } + end + def data File.read(self.full_filename) end diff --git a/test/fixtures/files/500.html b/test/fixtures/files/500.html new file mode 120000 index 0000000..7847d77 --- /dev/null +++ b/test/fixtures/files/500.html @@ -0,0 +1 @@ +../../../public/500.html \ No newline at end of file diff --git a/test/functional/content_viewer_controller_test.rb b/test/functional/content_viewer_controller_test.rb index f103e79..79d5c65 100644 --- a/test/functional/content_viewer_controller_test.rb +++ b/test/functional/content_viewer_controller_test.rb @@ -64,7 +64,19 @@ class ContentViewerControllerTest < ActionController::TestCase assert_response :missing end - should 'produce a download-like when article is not text/html' do + should 'produce a download-link when article is a uploaded file' do + profile = create_user('someone').person + html = UploadedFile.create! :uploaded_data => fixture_file_upload('/files/500.html', 'text/html'), :profile => profile + html.save! + + get :view_page, :profile => 'someone', :page => [ '500.html' ] + + assert_response :success + assert_match /^text\/html/, @response.headers['Content-Type'] + assert @response.headers['Content-Disposition'].present? + end + + should 'produce a download-link when article is not text/html' do # for example, RSS feeds profile = create_user('someone').person @@ -1254,7 +1266,7 @@ class ContentViewerControllerTest < ActionController::TestCase get 'view_page', :profile => profile.identifier, :page => article.path.split('/') assert_tag :tag => 'a', :attributes => { :href => "/#{profile.identifier}/#{article.path}?comment_page=2", :rel => 'next' } - end + end should 'not escape acceptable HTML in list of blog posts' do login_as('testinguser') -- libgit2 0.21.2