diff --git a/app/controllers/application.rb b/app/controllers/application.rb index 3dfd3923..a6200043 100644 --- a/app/controllers/application.rb +++ b/app/controllers/application.rb @@ -52,6 +52,21 @@ class ApplicationController < ActionController::Base check_authorization end + FILE_TYPES = { + '.exe' => 'application/octet-stream', + '.gif' => 'image/gif', + '.jpg' => 'image/jpeg', + '.pdf' => 'application/pdf', + '.png' => 'image/png', + '.txt' => 'text/plain', + '.zip' => 'application/zip' + } + + def send_file(file, options = {}) + options[:type] ||= (FILE_TYPES[File.extname(file)] || 'application/octet-stream') + super(file, options) + end + def in_a_web? not @web_name.nil? end diff --git a/app/controllers/file_controller.rb b/app/controllers/file_controller.rb index cd60f1cc..f3bc9e5d 100644 --- a/app/controllers/file_controller.rb +++ b/app/controllers/file_controller.rb @@ -4,18 +4,19 @@ require 'instiki_errors' class FileController < ApplicationController - layout 'default', :except => [:rss_feed, :rss_with_headlines, :tex, :export_tex, :export_html] + layout 'default' def file if have_file? send_file(file_path) else - render_text 'form' + logger.debug("File not found: #{file_path}") + # to template, which is a file upload form end end - + private - + def have_file? sanitize_file_name File.file?(file_path) @@ -24,7 +25,7 @@ class FileController < ApplicationController SANE_FILE_NAME = /[-_A-Za-z0-9]{1,255}/ def sanitize_file_name - raise Instiki::ValidationError.new("Invalid path") unless @file_name + raise Instiki::ValidationError.new("Invalid path: no file name") unless @file_name unless @file_name =~ SANE_FILE_NAME raise ValidationError.new("Invalid file name: '#{@file_name}'.\n" + "Only latin characters, digits, underscores and dashes are accepted.") @@ -32,7 +33,7 @@ class FileController < ApplicationController end def file_area - raise Instiki::ValidationError.new("Invalid path") unless @web_name + raise Instiki::ValidationError.new("Invalid path: no web name") unless @web_name file_area = File.expand_path("#{@wiki.storage_path}/#{@web_name}") FileUtils.mkdir_p(file_area) unless File.directory?(file_area) file_area diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb index 4bff91b0..c1676dd5 100755 --- a/app/controllers/wiki_controller.rb +++ b/app/controllers/wiki_controller.rb @@ -84,7 +84,7 @@ class WikiController < ApplicationController export_web_to_tex "#{file_path}.tex" unless FileTest.exists? "#{file_path}.tex" convert_tex_to_pdf "#{file_path}.tex" - send_file("#{file_path}.pdf") + send_file "#{file_path}.pdf" end def export_tex @@ -92,7 +92,7 @@ class WikiController < ApplicationController file_path = @wiki.storage_path + file_name export_web_to_tex(file_path) unless FileTest.exists?(file_path) - send_file(file_path) + send_file file_path end def feeds @@ -184,10 +184,10 @@ class WikiController < ApplicationController file_name = "#{safe_page_name}-#{@web.address}-#{@page.created_at.strftime('%Y-%m-%d-%H-%M-%S')}" file_path = @wiki.storage_path + file_name - export_page_to_tex(file_path + '.tex') unless FileTest.exists?(file_path + '.tex') + export_page_to_tex("#{file_path}.tex") unless FileTest.exists?("#{file_path}.tex") # NB: this is _very_ slow - convert_tex_to_pdf(file_path + '.tex') - send_file(file_path + '.pdf') + convert_tex_to_pdf("#{file_path}.tex") + send_file "#{file_path}.pdf" end def print @@ -300,7 +300,7 @@ class WikiController < ApplicationController end FileUtils.rm_rf(Dir[@wiki.storage_path + file_prefix + '*.zip']) FileUtils.mv(tmp_path, file_path) - send_file(file_path, :type => 'application/zip') + send_file file_path end def export_web_to_tex(file_path) diff --git a/app/views/file/file.rhtml b/app/views/file/file.rhtml new file mode 100644 index 00000000..0757e666 --- /dev/null +++ b/app/views/file/file.rhtml @@ -0,0 +1,3 @@ +

+TODO: Here should be a form for uploading files to Instiki +

\ No newline at end of file diff --git a/test/functional/file_controller_test.rb b/test/functional/file_controller_test.rb index 2e426855..2efa70ff 100644 --- a/test/functional/file_controller_test.rb +++ b/test/functional/file_controller_test.rb @@ -2,12 +2,16 @@ require File.dirname(__FILE__) + '/../test_helper' require 'file_controller' +require 'fileutils' # Raise errors beyond the default web-based presentation class FileController; def rescue_action(e) logger.error(e); raise e end; end class FileControllerTest < Test::Unit::TestCase + FILE_AREA = RAILS_ROOT + '/storage/test/wiki' + FileUtils.mkdir_p(FILE_AREA) unless File.directory?(FILE_AREA) + def setup setup_test_wiki setup_controller_test @@ -19,6 +23,29 @@ class FileControllerTest < Test::Unit::TestCase def test_file process 'file', 'web' => 'wiki', 'id' => 'foo.tgz' + + assert_success + assert_rendered_file 'file/file' + end + + def test_file_download_text_file + File.open(FILE_AREA + '/foo.txt', 'wb') { |f| f.write "aaa\nbbb\n" } + + r = process 'file', 'web' => 'wiki', 'id' => 'foo.txt' + + assert_success + assert_equal "aaa\nbbb\n", r.binary_content + assert_equal 'text/plain', r.headers['Content-Type'] + end + + def test_file_download_pdf_file + File.open(FILE_AREA + '/foo.pdf', 'wb') { |f| f.write "aaa\nbbb\n" } + + r = process 'file', 'web' => 'wiki', 'id' => 'foo.pdf' + + assert_success + assert_equal "aaa\nbbb\n", r.binary_content + assert_equal 'application/pdf', r.headers['Content-Type'] end end diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb index 03cc3796..9ec23832 100755 --- a/test/functional/wiki_controller_test.rb +++ b/test/functional/wiki_controller_test.rb @@ -2,7 +2,7 @@ # Uncomment the line below to enable pdflatex tests; don't forget to comment them again # commiting to SVN -# $INSTIKI_TEST_PDFLATEX = true +$INSTIKI_TEST_PDFLATEX = true require File.dirname(__FILE__) + '/../test_helper' require 'wiki_controller' @@ -181,7 +181,7 @@ class WikiControllerTest < Test::Unit::TestCase def test_export_pdf r = process 'export_pdf', 'web' => 'wiki1' assert_success - assert_equal 'application/octet_stream', r.headers['Content-Type'] + assert_equal 'application/pdf', r.headers['Content-Type'] assert_match /attachment; filename="wiki1-tex-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.pdf"/, r.headers['Content-Disposition'] content = r.binary_content @@ -202,7 +202,7 @@ class WikiControllerTest < Test::Unit::TestCase r = process 'export_tex', 'web' => 'wiki1' assert_success - assert_equal 'application/octet_stream', r.headers['Content-Type'] + assert_equal 'application/octet-stream', r.headers['Content-Type'] assert_match /attachment; filename="wiki1-tex-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.tex"/, r.headers['Content-Disposition'] content = r.binary_content @@ -310,7 +310,7 @@ class WikiControllerTest < Test::Unit::TestCase assert_equal '%PDF', content[0..3] assert_equal "EOF\n", content[-4..-1] - assert_equal 'application/octet_stream', r.headers['Content-Type'] + assert_equal 'application/pdf', r.headers['Content-Type'] assert_match /attachment; filename="HomePage-wiki1-\d\d\d\d-\d\d-\d\d-\d\d-\d\d-\d\d.pdf"/, r.headers['Content-Disposition'] end