Class: DAV4Rack::Controller
- Inherits:
-
Object
- Object
- DAV4Rack::Controller
- Includes:
- HTTPStatus, Utils
- Defined in:
- lib/dav4rack/controller.rb
Constant Summary
Constants included from HTTPStatus
Instance Attribute Summary collapse
-
#request ⇒ Object
readonly
Returns the value of attribute request.
-
#resource ⇒ Object
readonly
Returns the value of attribute resource.
-
#response ⇒ Object
readonly
Returns the value of attribute response.
Instance Method Summary collapse
- #add_dav_header ⇒ Object
-
#authenticate ⇒ Object
Perform authentication NOTE: Authentication will only be performed if the Resource has defined an #authenticate method.
-
#copy ⇒ Object
Return response to COPY.
-
#delete ⇒ Object
Return response to DELETE.
-
#get ⇒ Object
Return response to GET.
-
#head ⇒ Object
Return response to HEAD.
-
#initialize(request, response, options = {}) ⇒ Controller
constructor
- request
- Rack::Request response
- Rack::Response options
-
Options hash Create a new Controller.
-
#lock ⇒ Object
Lock current resource NOTE: This will pass an argument hash to Resource#lock and wait for a success/failure response.
-
#mkcol ⇒ Object
Return response to MKCOL.
-
#move(*args) ⇒ Object
- args
-
Only argument used: :copy Move Resource to new location.
-
#options ⇒ Object
Return response to OPTIONS.
-
#post ⇒ Object
Return response to POST.
-
#propfind ⇒ Object
Return response to PROPFIND.
-
#proppatch ⇒ Object
Return response to PROPPATCH.
-
#put ⇒ Object
Return response to PUT.
-
#unlock ⇒ Object
Unlock current resource.
-
#url_format(resource) ⇒ Object
- s
-
string Escape URL string.
-
#url_unescape(s) ⇒ Object
- s
-
string Unescape URL string.
Methods included from Utils
#to_element_hash, #to_element_key
Constructor Details
#initialize(request, response, options = {}) ⇒ Controller
- request
-
Rack::Request
- response
-
Rack::Response
- options
-
Options hash
Create a new Controller. NOTE: options will be passed to Resource
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/dav4rack/controller.rb', line 16 def initialize(request, response, ={}) raise Forbidden if request.path_info.include?('..') @request = request @response = response @options = @dav_extensions = .delete(:dav_extensions) || [] @always_include_dav_header = .delete(:always_include_dav_header) @resource = resource_class.new(actual_path, implied_path, @request, @response, @options) if(@always_include_dav_header) add_dav_header end end |
Instance Attribute Details
#request ⇒ Object (readonly)
Returns the value of attribute request.
9 10 11 |
# File 'lib/dav4rack/controller.rb', line 9 def request @request end |
#resource ⇒ Object (readonly)
Returns the value of attribute resource.
9 10 11 |
# File 'lib/dav4rack/controller.rb', line 9 def resource @resource end |
#response ⇒ Object (readonly)
Returns the value of attribute response.
9 10 11 |
# File 'lib/dav4rack/controller.rb', line 9 def response @response end |
Instance Method Details
#add_dav_header ⇒ Object
48 49 50 51 52 53 |
# File 'lib/dav4rack/controller.rb', line 48 def add_dav_header unless(response['Dav']) dav_support = %w(1 2) + @dav_extensions response['Dav'] = dav_support.join(', ') end end |
#authenticate ⇒ Object
Perform authentication NOTE: Authentication will only be performed if the Resource has defined an #authenticate method
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
# File 'lib/dav4rack/controller.rb', line 328 def authenticate authed = true if(resource.respond_to?(:authenticate, true)) authed = false uname = nil password = nil if(request.env['HTTP_AUTHORIZATION']) auth = Rack::Auth::Basic::Request.new(request.env) if(auth.basic? && auth.credentials) uname = auth.credentials[0] password = auth.credentials[1] end end authed = resource.send(:authenticate, uname, password) end raise Unauthorized unless authed end |
#copy ⇒ Object
Return response to COPY
140 141 142 |
# File 'lib/dav4rack/controller.rb', line 140 def copy move(:copy) end |
#delete ⇒ Object
Return response to DELETE
112 113 114 115 116 117 118 119 |
# File 'lib/dav4rack/controller.rb', line 112 def delete if(resource.exist?) resource.lock_check if resource.supports_locking? resource.delete else NotFound end end |
#get ⇒ Object
Return response to GET
76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/dav4rack/controller.rb', line 76 def get if(resource.exist?) res = resource.get(request, response) if(res == OK && !resource.collection?) response['Etag'] = resource.etag response['Content-Type'] = resource.content_type response['Content-Length'] = resource.content_length.to_s response['Last-Modified'] = resource.last_modified.httpdate end res else NotFound end end |
#head ⇒ Object
Return response to HEAD
64 65 66 67 68 69 70 71 72 73 |
# File 'lib/dav4rack/controller.rb', line 64 def head if(resource.exist?) response['Etag'] = resource.etag response['Content-Type'] = resource.content_type response['Last-Modified'] = resource.last_modified.httpdate OK else NotFound end end |
#lock ⇒ Object
Lock current resource NOTE: This will pass an argument hash to Resource#lock and wait for a success/failure response.
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 |
# File 'lib/dav4rack/controller.rb', line 268 def lock lockinfo = request_document.xpath("//#{ns}lockinfo") asked = {} asked[:timeout] = request.env['Timeout'].split(',').map{|x|x.strip} if request.env['Timeout'] asked[:depth] = depth unless([0, :infinity].include?(asked[:depth])) BadRequest else asked[:scope] = lockinfo.xpath("//#{ns}lockscope").children.find_all{|n|n.element?}.map{|n|n.name}.first asked[:type] = lockinfo.xpath("#{ns}locktype").children.find_all{|n|n.element?}.map{|n|n.name}.first asked[:owner] = lockinfo.xpath("//#{ns}owner/#{ns}href").children.map{|n|n.text}.first begin lock_time, locktoken = resource.lock(asked) render_xml(:prop) do |xml| xml.lockdiscovery do xml.activelock do if(asked[:scope]) xml.lockscope do xml.send(asked[:scope]) end end if(asked[:type]) xml.locktype do xml.send(asked[:type]) end end xml.depth asked[:depth].to_s xml.timeout lock_time ? "Second-#{lock_time}" : 'infinity' xml.locktoken do xml.href locktoken end if(asked[:owner]) xml.owner asked[:owner] end end end end response.headers['Lock-Token'] = locktoken response.status = resource.exist? ? OK : Created rescue LockFailure => e multistatus do |xml| e.path_status.each_pair do |path, status| xml.response do xml.href path xml.status "#{http_version} #{status.status_line}" end end end end end end |
#mkcol ⇒ Object
Return response to MKCOL
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/dav4rack/controller.rb', line 122 def mkcol resource.lock_check if resource.supports_locking? status = resource.make_collection gen_url = "#{scheme}://#{host}:#{port}#{url_format(resource)}" if status == Created if(resource.use_compat_mkcol_response?) multistatus do |xml| xml.response do xml.href gen_url xml.status "#{http_version} #{status.status_line}" end end else response['Location'] = gen_url status end end |
#move(*args) ⇒ Object
- args
-
Only argument used: :copy
Move Resource to new location. If :copy is provided, Resource will be copied (implementation ease)
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/dav4rack/controller.rb', line 147 def move(*args) unless(resource.exist?) NotFound else resource.lock_check if resource.supports_locking? && !args.include(:copy) destination = url_unescape(env['HTTP_DESTINATION'].sub(%r{https?://([^/]+)}, '')) dest_host = $1 if(dest_host && dest_host.gsub(/:\d{2,5}$/, '') != request.host) BadGateway elsif(destination == resource.public_path) Forbidden else collection = resource.collection? dest = resource_class.new(destination, clean_path(destination), @request, @response, @options.merge(:user => resource.user)) status = nil if(args.include?(:copy)) status = resource.copy(dest, overwrite) else return Conflict unless depth.is_a?(Symbol) || depth > 1 status = resource.move(dest, overwrite) end response['Location'] = "#{scheme}://#{host}:#{port}#{url_format(dest)}" if status == Created # RFC 2518 if collection multistatus do |xml| xml.response do xml.href "#{scheme}://#{host}:#{port}#{url_format(status == Created ? dest : resource)}" xml.status "#{http_version} #{status.status_line}" end end else status end end end end |
#options ⇒ Object
Return response to OPTIONS
56 57 58 59 60 61 |
# File 'lib/dav4rack/controller.rb', line 56 def add_dav_header response['Allow'] = 'OPTIONS,HEAD,GET,PUT,POST,DELETE,PROPFIND,PROPPATCH,MKCOL,COPY,MOVE,LOCK,UNLOCK' response['Ms-Author-Via'] = 'DAV' OK end |
#post ⇒ Object
Return response to POST
107 108 109 |
# File 'lib/dav4rack/controller.rb', line 107 def post resource.post(request, response) end |
#propfind ⇒ Object
Return response to PROPFIND
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
# File 'lib/dav4rack/controller.rb', line 185 def propfind unless(resource.exist?) NotFound else unless(request_document.xpath("//#{ns}propfind/#{ns}allprop").empty?) properties = resource.properties else check = request_document.xpath("//#{ns}propfind") if(check && !check.empty?) properties = request_document.xpath( "//#{ns}propfind/#{ns}prop" ).children.find_all{ |item| item.element? }.map{ |item| # We should do this, but Nokogiri transforms prefix w/ null href into # something valid. Oops. # TODO: Hacky grep fix that's horrible hsh = to_element_hash(item) if(hsh.namespace.nil? && !ns.empty?) raise BadRequest if request_document.to_s.scan(%r{<#{item.name}[^>]+xmlns=""}).empty? end hsh }.compact else raise BadRequest end 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, properties.empty? ? resource.properties : properties)) end end end end end |
#proppatch ⇒ Object
Return response to PROPPATCH
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/dav4rack/controller.rb', line 228 def proppatch unless(resource.exist?) NotFound else resource.lock_check if resource.supports_locking? prop_actions = [] request_document.xpath("/#{ns}propertyupdate").children.each do |element| case element.name when 'set', 'remove' prp = element.children.detect{|e|e.name == 'prop'} if(prp) prp.children.each do |elm| next if elm.name == 'text' prop_actions << {:type => element.name, :name => to_element_hash(elm), :value => elm.text} end end end end multistatus do |xml| find_resources.each do |resource| xml.response do xml.href "#{scheme}://#{host}:#{port}#{url_format(resource)}" prop_actions.each do |action| case action[:type] when 'set' propstats(xml, set_properties(resource, action[:name] => action[:value])) when 'remove' rm_properties(resource, action[:name] => action[:value]) end end end end end end end |
#put ⇒ Object
Return response to PUT
92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/dav4rack/controller.rb', line 92 def put if(resource.collection?) Forbidden elsif(!resource.parent_exists? || !resource.parent_collection?) Conflict else resource.lock_check if resource.supports_locking? status = resource.put(request, response) response['Location'] = "#{scheme}://#{host}:#{port}#{url_format(resource)}" if status == Created response.body = response['Location'] status end end |
#unlock ⇒ Object
Unlock current resource
321 322 323 |
# File 'lib/dav4rack/controller.rb', line 321 def unlock resource.unlock(lock_token) end |
#url_format(resource) ⇒ Object
- s
-
string
Escape URL string
34 35 36 37 38 39 40 |
# File 'lib/dav4rack/controller.rb', line 34 def url_format(resource) ret = URI.escape(resource.public_path) if resource.collection? and ret[-1,1] != '/' ret += '/' end ret end |
#url_unescape(s) ⇒ Object
- s
-
string
Unescape URL string
44 45 46 |
# File 'lib/dav4rack/controller.rb', line 44 def url_unescape(s) URI.unescape(s) end |