Parse fix applied for webdav PUT method, where .Net / Office over WebDav pushes content with text/xml mime type. Rails stack automatically will try to parse XML, however unfortunately as content is
not XML, it ends up failing. "init.rb" has a hook adding RedmineDmsf::NoParse into Rails middleware a step before content parsing occurs, and will rewrite content type on put method, within specified target area (identified in init.rb). Controller has been added to override options function (maybe removed later on).
This commit is contained in:
parent
3bd5d93479
commit
c76556c507
@ -92,5 +92,6 @@ RedmineApp::Application.routes.draw do
|
||||
# :root => Rails.root.to_s,
|
||||
:root_uri_path => "/dmsf/webdav",
|
||||
:resource_class => RedmineDmsf::Webdav::ResourceProxy,
|
||||
:controller_class => RedmineDmsf::Webdav::Controller
|
||||
), :at => "/dmsf/webdav"
|
||||
end
|
||||
|
||||
14
init.rb
14
init.rb
@ -17,9 +17,16 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
require 'redmine'
|
||||
#require 'dispatcher'
|
||||
require 'redmine_dmsf'
|
||||
|
||||
#
|
||||
# This may need to be configurable
|
||||
#
|
||||
Rails.configuration.middleware.insert_before(ActionDispatch::ParamsParser,
|
||||
RedmineDmsf::NoParse, :urls => ['/dmsf/webdav'])
|
||||
|
||||
|
||||
|
||||
#Dispatcher.to_prepare :redmine_dmsf do
|
||||
Rails.configuration.to_prepare do
|
||||
unless ProjectsHelper.included_modules.include?(ProjectTabsExtended)
|
||||
ProjectsHelper.send(:include, ProjectTabsExtended)
|
||||
@ -30,6 +37,9 @@ Rails.configuration.to_prepare do
|
||||
end
|
||||
|
||||
Project.send(:include, RedmineDmsf::Patches::ProjectPatch)
|
||||
|
||||
#ActiveSupport::XmlMini.backend = 'Nokogiri'
|
||||
|
||||
end
|
||||
|
||||
Redmine::Plugin.register :redmine_dmsf do
|
||||
|
||||
@ -2,6 +2,7 @@ require 'redmine_dmsf/patches/custom_fields_helper'
|
||||
require 'redmine_dmsf/patches/acts_as_customizable'
|
||||
require 'redmine_dmsf/patches/project_patch'
|
||||
require 'redmine_dmsf/webdav'
|
||||
require 'redmine_dmsf/no_parse'
|
||||
|
||||
module RedmineDmsf
|
||||
end
|
||||
|
||||
25
lib/redmine_dmsf/no_parse.rb
Normal file
25
lib/redmine_dmsf/no_parse.rb
Normal file
@ -0,0 +1,25 @@
|
||||
module RedmineDmsf
|
||||
class NoParse
|
||||
def initialize(app, options={})
|
||||
@app = app
|
||||
@urls = options[:urls]
|
||||
end
|
||||
|
||||
def call(env)
|
||||
if env['REQUEST_METHOD'] == "PUT" && env.has_key?('CONTENT_TYPE') then
|
||||
if (@urls.dup.delete_if {|x| !env['PATH_INFO'].starts_with? x}.length > 0) then
|
||||
logger "RedmineDmsf::NoParse prevented mime parsing for PUT #{env['PATH_INFO']}"
|
||||
env['CONTENT_TYPE'] = 'text/plain'
|
||||
end
|
||||
end
|
||||
@app.call(env)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def logger(env)
|
||||
env['action_dispatch.logger'] || Logger.new($stdout)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@ -1,7 +1,7 @@
|
||||
# Load up classes that make up our webdav solution ontop
|
||||
# of DAV4Rack
|
||||
require 'redmine_dmsf/webdav/resource_proxy'
|
||||
|
||||
require 'redmine_dmsf/webdav/base_resource'
|
||||
|
||||
require 'redmine_dmsf/webdav/index_resource'
|
||||
require 'redmine_dmsf/webdav/project_resource'
|
||||
require 'redmine_dmsf/webdav/dmsf_resource'
|
||||
|
||||
@ -51,6 +51,7 @@ module RedmineDmsf
|
||||
|
||||
def parent
|
||||
p = @__proxy.parent
|
||||
return nil if p.nil?
|
||||
return p.resource.nil? ? p : p.resource
|
||||
end
|
||||
|
||||
|
||||
49
lib/redmine_dmsf/webdav/controller.rb
Normal file
49
lib/redmine_dmsf/webdav/controller.rb
Normal file
@ -0,0 +1,49 @@
|
||||
module RedmineDmsf
|
||||
module Webdav
|
||||
class Controller < DAV4Rack::Controller
|
||||
|
||||
#Overload default options
|
||||
def options
|
||||
response["Allow"] = 'OPTIONS,HEAD,GET,PUT,POST,DELETE,PROPFIND,PROPPATCH,MKCOL,COPY,MOVE,LOCK,UNLOCK'
|
||||
response["Dav"] = "1,2,3"
|
||||
response["Ms-Author-Via"] = "DAV"
|
||||
OK
|
||||
end
|
||||
|
||||
#Overload the default propfind function with this
|
||||
def propfind
|
||||
unless(resource.exist?)
|
||||
NotFound
|
||||
else
|
||||
unless(request_document.xpath("//#{ns}propfind/#{ns}allprop").empty?)
|
||||
names = resource.property_names
|
||||
else
|
||||
names = (
|
||||
ns.empty? ? request_document.remove_namespaces! : request_document
|
||||
).xpath(
|
||||
"//#{ns}propfind/#{ns}prop"
|
||||
).children.find_all{ |item|
|
||||
item.element? && item.name.start_with?(ns)
|
||||
}.map{ |item|
|
||||
item.name.sub("#{ns}::", '')
|
||||
}
|
||||
names = resource.property_names if names.empty?
|
||||
end
|
||||
multistatus do |xml|
|
||||
find_resources.each do |resource|
|
||||
xml.response do
|
||||
unless(resource.propstat_relative_path)
|
||||
xml.href "#{scheme}://#{host}:#{port}#{url_format(resource)}"
|
||||
else
|
||||
xml.href url_format(resource)
|
||||
end
|
||||
propstats(xml, get_properties(resource, names))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -167,7 +167,6 @@ module RedmineDmsf
|
||||
#
|
||||
# Create a DmsfFolder at location requested, only if parent is a folder (or root)
|
||||
def make_collection
|
||||
debugger
|
||||
if (request.body.read.to_s == '')
|
||||
return MethodNotAllowed if exist? #If we already exist, why waste the time trying to save?
|
||||
parent_folder = nil
|
||||
|
||||
@ -9,6 +9,7 @@ module RedmineDmsf
|
||||
def children
|
||||
#caching for repeat usage
|
||||
return @children unless @children.nil?
|
||||
return [] if project.nil? || project.id.nil?
|
||||
@children = []
|
||||
DmsfFolder.project_root_folders(project).map do |p|
|
||||
@children.push child(p.title, p)
|
||||
@ -65,6 +66,13 @@ module RedmineDmsf
|
||||
OK
|
||||
end
|
||||
|
||||
def folder
|
||||
nil
|
||||
end
|
||||
def file
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -30,7 +30,7 @@ module RedmineDmsf
|
||||
# going to fork it to ensure compliance, checking the request method in the authentication
|
||||
# seems the next best step, if the request method is OPTIONS return true, controller will simply
|
||||
# call the options method within, which accesses nothing, just returns headers about dav env.
|
||||
return false if (@request.request_method.downcase == "options")
|
||||
return true if ( @request.request_method.downcase == "options" && ( path == "/" || path.empty? ) )
|
||||
User.current = User.try_to_login(username, password) || nil
|
||||
return !User.current.anonymous? unless User.current.nil?
|
||||
false
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user