Pass 1 of webdav (VERY ROUGH) - Functional on Get/Head (Web based listing) and also webdav listing and downloading of resources.
User based authentication and tracking of downloads, however security model not implemented yet.
This commit is contained in:
parent
fa4207dfce
commit
2e431568d6
@ -1,6 +1,9 @@
|
||||
module RedmineDmsf
|
||||
module Webdav
|
||||
class BaseResource < DAV4Rack::Resource
|
||||
include Redmine::I18n
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
|
||||
DIR_FILE = "<tr><td class=\"name\"><a href=\"%s\">%s</a></td><td class=\"size\">%s</td><td class=\"type\">%s</td><td class=\"mtime\">%s</td></tr>"
|
||||
|
||||
@ -24,7 +27,15 @@ module RedmineDmsf
|
||||
|
||||
@response.body = ""
|
||||
Confict unless collection?
|
||||
entities = children.map{|child| DIR_FILE % [child.public_path.html_safe, child.long_name || child.name, "-", child.special_type || child.content_type, child.last_modified]} * "\n"
|
||||
entities = children.map{|child|
|
||||
DIR_FILE % [
|
||||
child.public_path,
|
||||
child.long_name || child.name,
|
||||
child.collection? ? '-' : number_to_human_size(child.content_length),
|
||||
child.special_type || child.content_type,
|
||||
child.last_modified
|
||||
]
|
||||
} * "\n"
|
||||
@response.body << index_page % [ path.empty? ? "/" : path, path.empty? ? "/" : path , entities ]
|
||||
end
|
||||
|
||||
@ -62,6 +73,12 @@ table { width:100%%; }
|
||||
end
|
||||
|
||||
protected
|
||||
def basename
|
||||
File.basename(path)
|
||||
end
|
||||
def dirname
|
||||
File.dirname(path)
|
||||
end
|
||||
def Project
|
||||
return @Project unless @Project.nil?
|
||||
pinfo = @path.split('/').drop(1)
|
||||
@ -72,6 +89,9 @@ table { width:100%%; }
|
||||
end
|
||||
end
|
||||
end
|
||||
def projectless_path
|
||||
'/'+path.split('/').drop(2).join('/')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
132
lib/redmine_dmsf/webdav/dmsf_resource.rb
Normal file
132
lib/redmine_dmsf/webdav/dmsf_resource.rb
Normal file
@ -0,0 +1,132 @@
|
||||
module RedmineDmsf
|
||||
module Webdav
|
||||
class DmsfResource < BaseResource
|
||||
|
||||
def children
|
||||
NotFound unless exist? && folder?
|
||||
return @children unless @children.nil?
|
||||
@children = []
|
||||
@_folderdata.subfolders.map do |p|
|
||||
@children.push child(p.title, p)
|
||||
end
|
||||
@_folderdata.files.map do |p|
|
||||
@children.push child(p.name, p)
|
||||
end
|
||||
@children
|
||||
|
||||
end
|
||||
|
||||
def exist?
|
||||
folder? || file?
|
||||
end
|
||||
|
||||
def collection?
|
||||
exist? && folder?
|
||||
end
|
||||
|
||||
def folder?
|
||||
return @_folder unless @_folder.nil?
|
||||
@_folder = false
|
||||
folders = DmsfFolder.find(:all, :conditions => ["project_id = :project_id", {:project_id => self.Project.id}], :order => "title ASC")
|
||||
folders.delete_if {|x| x.title != basename}
|
||||
return false unless folders.length > 0
|
||||
if (folders.length > 1) then
|
||||
folders.delete_if {|x| x.dmsf_path_str != projectless_path}
|
||||
return false unless folders.length > 0
|
||||
@_folder=true
|
||||
@_folderdata = folders[0]
|
||||
else
|
||||
if ('/'+folders[0].dmsf_path_str == projectless_path) then
|
||||
@_folder=true
|
||||
@_folderdata = folders[0]
|
||||
else
|
||||
@_folder= false
|
||||
end
|
||||
end
|
||||
@_folder
|
||||
end
|
||||
|
||||
def file?
|
||||
return @_file unless @_file.nil?
|
||||
@_file = false
|
||||
files = DmsfFile.find(:all, :conditions => ["project_id = :project_id AND name = :file_name AND deleted = :deleted", {:project_id => self.Project.id, :file_name => basename, :deleted => false}], :order => "name ASC")
|
||||
files.delete_if {|x| File.dirname('/'+x.dmsf_path_str) != File.dirname(projectless_path)}
|
||||
if files.length > 0
|
||||
@_filedata = files[0]
|
||||
@_file = true
|
||||
end
|
||||
end
|
||||
|
||||
def content_type
|
||||
if folder? then
|
||||
"inode/directory"
|
||||
elsif file?
|
||||
@_filedata.last_revision.detect_content_type
|
||||
else
|
||||
NotFound
|
||||
end
|
||||
end
|
||||
|
||||
def creation_date
|
||||
if folder?
|
||||
@_folderdata.created_at
|
||||
elsif file?
|
||||
@_filedata.created_at
|
||||
else
|
||||
NotFound
|
||||
end
|
||||
end
|
||||
|
||||
def last_modified
|
||||
if folder?
|
||||
@_folderdata.updated_at
|
||||
elsif file?
|
||||
@_filedata.updated_at
|
||||
else
|
||||
NotFound
|
||||
end
|
||||
end
|
||||
|
||||
def etag
|
||||
filesize = file? ? @_filedata.size : 4096;
|
||||
fileino = file? ? File.stat(@_filedata.last_revision.disk_file).ino : 2;
|
||||
sprintf('%x-%x-%x', fileino, filesize, last_modified.to_i)
|
||||
end
|
||||
|
||||
def content_length
|
||||
file? ? @_filedata.size : 4096;
|
||||
end
|
||||
|
||||
def special_type
|
||||
l(:field_folder) if folder?
|
||||
end
|
||||
|
||||
def get(request, response)
|
||||
raise NotFound unless exist?
|
||||
if collection?
|
||||
html_display
|
||||
response['Content-Length'] = response.body.bytesize.to_s
|
||||
else
|
||||
response.body = download
|
||||
end
|
||||
OK
|
||||
end
|
||||
|
||||
protected
|
||||
def download
|
||||
raise NotFound unless file?
|
||||
#log_activity("downloaded")
|
||||
if @request.env['HTTP_RANGE'].nil?
|
||||
access = DmsfFileRevisionAccess.new(:user_id => User.current.id, :dmsf_file_revision_id => @_filedata.last_revision.id,
|
||||
:action => DmsfFileRevisionAccess::DownloadAction)
|
||||
access.save!
|
||||
end
|
||||
|
||||
Download.new(@_filedata.last_revision.disk_file)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
32
lib/redmine_dmsf/webdav/download.rb
Normal file
32
lib/redmine_dmsf/webdav/download.rb
Normal file
@ -0,0 +1,32 @@
|
||||
require 'time'
|
||||
require 'rack/utils'
|
||||
require 'rack/mime'
|
||||
|
||||
module RedmineDmsf
|
||||
module Webdav
|
||||
class Download < Rack::File
|
||||
def initialize(root, cache_control = nil)
|
||||
@path = root
|
||||
@cache_control = cache_control
|
||||
end
|
||||
|
||||
def _call(env)
|
||||
unless ALLOWED_VERBS.include? env["REQUEST_METHOD"]
|
||||
return fail(405, "Method Not Allowed")
|
||||
end
|
||||
|
||||
available = begin
|
||||
F.file?(@path) && F.readable?(@path)
|
||||
rescue SystemCallError
|
||||
false
|
||||
end
|
||||
|
||||
if available
|
||||
serving(env)
|
||||
else
|
||||
raise NotFound
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -9,21 +9,18 @@ module RedmineDmsf
|
||||
def children
|
||||
#caching for repeat usage
|
||||
return @children unless @children.nil?
|
||||
@children = []
|
||||
DmsfFolder.project_root_folders(self.Project).map do |p|
|
||||
child p.title, p
|
||||
@children.push child(p.title, p)
|
||||
end
|
||||
DmsfFile.project_root_files(self.Project).map do |p|
|
||||
child p.display_name, p
|
||||
@children.push child(p.name, p)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def name
|
||||
self.Project.name unless self.Project.nil?
|
||||
@children
|
||||
end
|
||||
|
||||
def exist?
|
||||
!self.Project.nil?
|
||||
!(self.Project.nil? || User.current.anonymous?)
|
||||
end
|
||||
|
||||
def collection?
|
||||
@ -55,7 +52,7 @@ module RedmineDmsf
|
||||
end
|
||||
|
||||
def special_type
|
||||
"Project"
|
||||
l(:field_project)
|
||||
end
|
||||
|
||||
def content_length
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user