diff --git a/lib/redmine_dmsf/webdav/controller.rb b/lib/redmine_dmsf/webdav/controller.rb index 9d52032c..19a33570 100644 --- a/lib/redmine_dmsf/webdav/controller.rb +++ b/lib/redmine_dmsf/webdav/controller.rb @@ -28,16 +28,32 @@ module RedmineDmsf # Return response to OPTIONS def options - # Always return MethodNotAllowed(405) because how MsOffice uses anonymous OPTIONS request. - # See https://support.microsoft.com/en-us/kb/2019105 - MethodNotAllowed + # exist? returns false if user is anonymous for ProjectResource and DmsfResource, but not for IndexResource. + unless(resource.exist? || (User.current && User.current.anonymous?)) + # Return NotFound if resource does not exist and the request is not anonymous. + NotFound + else + if request.env.has_key?('HTTP_X_OFFICE_MAJOR_VERSION') && User.current && User.current.anonymous? + # Anonymous request from MsOffice, respond 405. + # If responding with 401 then MsOffice will fail. + # If responding with 200 then MsOffice will think that anonymous access is ok for everything. + # Responding with 405 is a workaround found in https://support.microsoft.com/en-us/kb/2019105 + MethodNotAllowed + else + resource.options + end + end end # Return response to HEAD def head - # Don't check resource.exist? because it returns false for anonymous requests and MsOffice's uses anonymous HEAD requests. - # See https://support.microsoft.com/en-us/kb/2019105 - resource.head(request, response) + # exist? returns false if user is anonymous for ProjectResource and DmsfResource, but not for IndexResource. + unless(resource.exist? || (request.env.has_key?('HTTP_X_OFFICE_MAJOR_VERSION') && User.current && User.current.anonymous?)) + # Return NotFound if resource does not exist and the request is not from an anonymous MsOffice product. + NotFound + else + resource.head(request, response) + end end # Return response to PROPFIND diff --git a/lib/redmine_dmsf/webdav/dmsf_resource.rb b/lib/redmine_dmsf/webdav/dmsf_resource.rb index f12dde95..befbdbc0 100644 --- a/lib/redmine_dmsf/webdav/dmsf_resource.rb +++ b/lib/redmine_dmsf/webdav/dmsf_resource.rb @@ -201,6 +201,7 @@ module RedmineDmsf ## def head(request, response) raise NotFound unless project && project.module_enabled?('dmsf') && (folder || file) + if collection? html_display(true) response['Content-Length'] = response.body.bytesize.to_s @@ -628,6 +629,13 @@ module RedmineDmsf end end + def options_req + response["Allow"] = 'OPTIONS,HEAD,GET,PUT,POST,DELETE,PROPFIND,PROPPATCH,MKCOL,COPY,MOVE,LOCK,UNLOCK' + response["Dav"] = '1, 2' + response["Ms-Author-Via"] = "DAV" + OK + end + private # Prepare file for download using Rack functionality: # Download (see RedmineDmsf::Webdav::Download) extends Rack::File to allow single-file diff --git a/lib/redmine_dmsf/webdav/index_resource.rb b/lib/redmine_dmsf/webdav/index_resource.rb index 0acf48e0..7ad71a92 100644 --- a/lib/redmine_dmsf/webdav/index_resource.rb +++ b/lib/redmine_dmsf/webdav/index_resource.rb @@ -80,6 +80,14 @@ module RedmineDmsf OK end + def options_req + response["Allow"] = 'OPTIONS,HEAD,GET,PUT,POST,DELETE,PROPFIND,PROPPATCH,MKCOL,COPY,MOVE,LOCK,UNLOCK' + #response["Allow"] = 'OPTIONS,PROPFIND' + response["Dav"] = '1, 2' + response["Ms-Author-Via"] = "DAV" + OK + end + # Bugfix: Ensure that this level never indicates a parent def parent nil diff --git a/lib/redmine_dmsf/webdav/project_resource.rb b/lib/redmine_dmsf/webdav/project_resource.rb index 36a9588b..47a79df0 100644 --- a/lib/redmine_dmsf/webdav/project_resource.rb +++ b/lib/redmine_dmsf/webdav/project_resource.rb @@ -81,9 +81,14 @@ module RedmineDmsf end def head(request, response) - html_display(true) - response['Content-Length'] = response.body.bytesize.to_s - OK + # HEAD must be allowed even for anonymous users, so just verify that the project exists and that the dmsf module is enabled. + if project.nil? || !project.module_enabled?('dmsf') + NotFound + else + html_display(true) + response['Content-Length'] = response.body.bytesize.to_s + OK + end end def get(request, response) @@ -92,6 +97,13 @@ module RedmineDmsf OK end + def options_req + response["Allow"] = 'OPTIONS,HEAD,GET,PUT,POST,DELETE,PROPFIND,PROPPATCH,MKCOL,COPY,MOVE,LOCK,UNLOCK' + response["Dav"] = '1, 2' + response["Ms-Author-Via"] = "DAV" + OK + end + def folder nil end diff --git a/lib/redmine_dmsf/webdav/resource_proxy.rb b/lib/redmine_dmsf/webdav/resource_proxy.rb index 782ff67d..06999d0d 100644 --- a/lib/redmine_dmsf/webdav/resource_proxy.rb +++ b/lib/redmine_dmsf/webdav/resource_proxy.rb @@ -52,9 +52,12 @@ module RedmineDmsf # 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 true if @request.request_method.downcase == 'options' && (path == '/' || path.empty?) - # MsOffice does anonymous OPTIONS and HEAD requests. + + # Allow anonymous OPTIONS requests. return true if @request.request_method.downcase == 'options' + # Allow anonymous HEAD requests. return true if @request.request_method.downcase == 'head' + return false unless username && password User.current = User.try_to_login(username, password) return User.current && !User.current.anonymous? @@ -164,6 +167,9 @@ module RedmineDmsf @resource_c.properties end + def options + @resource_c.options_req + end end end end