File download (primitive implementation)

This commit is contained in:
Alexey Verkhovsky 2005-01-22 02:49:52 +00:00
parent 9d90901cd0
commit e9a419c40f
6 changed files with 73 additions and 55 deletions

View file

@ -25,12 +25,38 @@ class ApplicationController < ActionController::Base
protected protected
def wiki def authorized?
$instiki_wiki_service @web.nil? ||
@web.password.nil? ||
cookies['web_address'] == @web.password ||
password_check(@params['password'])
end
def check_authorization
if in_a_web? and
not authorized? and
not %w( login authenticate published ).include?(@action_name)
redirect_to :action => 'login'
return false
end
end
def connect_to_model
@action_name = @params['action'] || 'index'
@web_name = @params['web']
@wiki = wiki
@web = @wiki.webs[@web_name] unless @web_name.nil?
@page_name = @file_name = @params['id']
@page = @wiki.read_page(@web_name, @page_name) unless @page_name.nil?
@author = cookies['author'] || 'AnonymousCoward'
check_authorization
end
def in_a_web?
not @web_name.nil?
end end
@@REMEMBER_NOT = ['locked', 'save'] @@REMEMBER_NOT = ['locked', 'save']
def remember_location def remember_location
if @response.headers['Status'] == '200 OK' if @response.headers['Status'] == '200 OK'
unless @@REMEMBER_NOT.include? action_name or @request.method != :get unless @@REMEMBER_NOT.include? action_name or @request.method != :get
@ -58,28 +84,8 @@ class ApplicationController < ActionController::Base
@response.headers['Content-Type'] = 'text/html; charset=UTF-8' @response.headers['Content-Type'] = 'text/html; charset=UTF-8'
end end
def connect_to_model def wiki
@action_name = @params['action'] || 'index' $instiki_wiki_service
@web_name = @params['web']
@wiki = wiki
@web = @wiki.webs[@web_name] unless @web_name.nil?
@page_name = @params['id']
@page = @wiki.read_page(@web_name, @page_name) unless @page_name.nil?
@author = cookies['author'] || 'AnonymousCoward'
check_authorization(@action_name)
end
def check_authorization(action_name)
if in_a_web? and
not authorized? and
not %w( login authenticate published ).include?(action_name)
redirect_to :action => 'login'
return false
end
end
def in_a_web?
not @web_name.nil?
end end
end end

View file

@ -1,12 +1,14 @@
require 'fileutils'
require 'application' require 'application'
require 'instiki_errors'
class FileController < ApplicationController class FileController < ApplicationController
layout 'default', :except => [:rss_feed, :rss_with_headlines, :tex, :export_tex, :export_html] layout 'default', :except => [:rss_feed, :rss_with_headlines, :tex, :export_tex, :export_html]
def file def file
if have_file?(@params['id']) if have_file?
render_text 'Download file' send_file(file_path)
else else
render_text 'form' render_text 'form'
end end
@ -14,18 +16,30 @@ class FileController < ApplicationController
private private
def have_file?(file_name) def have_file?
sanitize_file_name(file_name) sanitize_file_name
@wiki.storage_path File.file?(file_path)
end end
SANE_FILE_NAME = /[-_A-Za-z0-9]{1,255}/ SANE_FILE_NAME = /[-_A-Za-z0-9]{1,255}/
def sanitize_file_name(file_name)
unless file_name =~ SANE_FILE_NAME def sanitize_file_name
raise "Invalid file name: '#{file_name}'.\n" + raise Instiki::ValidationError.new("Invalid path") unless @file_name
"Only latin characters, digits, underscores and dashes are accepted." unless @file_name =~ SANE_FILE_NAME
raise ValidationError.new("Invalid file name: '#{@file_name}'.\n" +
"Only latin characters, digits, underscores and dashes are accepted.")
end end
end end
def file_area
raise Instiki::ValidationError.new("Invalid path") 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
end
def file_path
"#{file_area}/#{@file_name}"
end
end end

View file

@ -80,7 +80,7 @@ class WikiController < ApplicationController
def export_pdf def export_pdf
file_name = "#{@web.address}-tex-#{@web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}" file_name = "#{@web.address}-tex-#{@web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}"
file_path = WikiService.storage_path + file_name file_path = @wiki.storage_path + file_name
export_web_to_tex "#{file_path}.tex" unless FileTest.exists? "#{file_path}.tex" export_web_to_tex "#{file_path}.tex" unless FileTest.exists? "#{file_path}.tex"
convert_tex_to_pdf "#{file_path}.tex" convert_tex_to_pdf "#{file_path}.tex"
@ -89,7 +89,7 @@ class WikiController < ApplicationController
def export_tex def export_tex
file_name = "#{@web.address}-tex-#{@web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}.tex" file_name = "#{@web.address}-tex-#{@web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')}.tex"
file_path = WikiService.storage_path + file_name file_path = @wiki.storage_path + file_name
export_web_to_tex(file_path) unless FileTest.exists?(file_path) export_web_to_tex(file_path) unless FileTest.exists?(file_path)
send_file(file_path) send_file(file_path)
@ -182,7 +182,7 @@ class WikiController < ApplicationController
page = wiki.read_page(@web_name, @page_name) page = wiki.read_page(@web_name, @page_name)
safe_page_name = @page.name.gsub(/\W/, '') safe_page_name = @page.name.gsub(/\W/, '')
file_name = "#{safe_page_name}-#{@web.address}-#{@page.created_at.strftime('%Y-%m-%d-%H-%M-%S')}" file_name = "#{safe_page_name}-#{@web.address}-#{@page.created_at.strftime('%Y-%m-%d-%H-%M-%S')}"
file_path = WikiService.storage_path + file_name 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 # NB: this is _very_ slow
@ -263,13 +263,6 @@ class WikiController < ApplicationController
private private
def authorized?
@web.nil? ||
@web.password.nil? ||
cookies['web_address'] == @web.password ||
password_check(@params['password'])
end
def convert_tex_to_pdf(tex_path) def convert_tex_to_pdf(tex_path)
# TODO remove earlier PDF files with the same prefix # TODO remove earlier PDF files with the same prefix
# TODO handle gracefully situation where pdflatex is not available # TODO handle gracefully situation where pdflatex is not available
@ -285,7 +278,7 @@ class WikiController < ApplicationController
file_prefix = "#{@web.address}-#{file_type}-" file_prefix = "#{@web.address}-#{file_type}-"
timestamp = @web.revised_on.strftime('%Y-%m-%d-%H-%M-%S') timestamp = @web.revised_on.strftime('%Y-%m-%d-%H-%M-%S')
file_path = WikiService.storage_path + file_prefix + timestamp + '.zip' file_path = @wiki.storage_path + file_prefix + timestamp + '.zip'
tmp_path = "#{file_path}.tmp" tmp_path = "#{file_path}.tmp"
Zip::ZipOutputStream.open(tmp_path) do |zip_out| Zip::ZipOutputStream.open(tmp_path) do |zip_out|
@ -305,7 +298,7 @@ class WikiController < ApplicationController
EOL EOL
end end
end end
FileUtils.rm_rf(Dir[WikiService.storage_path + file_prefix + '*.zip']) FileUtils.rm_rf(Dir[@wiki.storage_path + file_prefix + '*.zip'])
FileUtils.mv(tmp_path, file_path) FileUtils.mv(tmp_path, file_path)
send_file(file_path, :type => 'application/zip') send_file(file_path, :type => 'application/zip')
end end

View file

@ -91,6 +91,10 @@ module AbstractWikiService
page page
end end
def storage_path
self.class.storage_path
end
private private
def settings_changed?(web, markup, safe_mode, brackets_only) def settings_changed?(web, markup, safe_mode, brackets_only)
web.markup != markup || web.markup != markup ||
@ -106,19 +110,20 @@ class WikiService
# These methods do not change the state of persistent objects, and # These methods do not change the state of persistent objects, and
# should not be ogged by Madeleine # should not be ogged by Madeleine
automatic_read_only :authenticate, :read_page, :setup?, :webs automatic_read_only :authenticate, :read_page, :setup?, :webs, :storage_path
@@storage_path = './storage/' @@storage_path = './storage/'
class << self class << self
def storage_path
@@storage_path
end
def storage_path=(storage_path) def storage_path=(storage_path)
@@storage_path = storage_path @@storage_path = storage_path
end end
def storage_path
@@storage_path
end
def clean_storage def clean_storage
MadeleineServer.clean_storage(self) MadeleineServer.clean_storage(self)
end end

View file

@ -18,7 +18,7 @@ class FileControllerTest < Test::Unit::TestCase
end end
def test_file def test_file
process 'file', 'id' => 'foo.tgz' process 'file', 'web' => 'wiki', 'id' => 'foo.tgz'
end end
end end

View file

@ -56,7 +56,7 @@ class WikiServiceWithNoPersistence
end end
def storage_path def storage_path
RAILS_ROOT + '/storage/test' RAILS_ROOT + '/storage/test/'
end end
end end