Class: DAV4Rack::Controller
- Inherits:
-
Object
- Object
- DAV4Rack::Controller
- Includes:
- HTTPStatus
- 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
-
#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 respoonse to PROPFIND.
-
#proppatch ⇒ Object
Return response to PROPPATCH.
-
#put ⇒ Object
Return response to PUT.
-
#unlock ⇒ Object
Unlock current resource.
-
#url_escape(s) ⇒ Object
- s
-
string Escape URL string.
-
#url_unescape(s) ⇒ Object
- s
-
string Unescape URL string.
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
13 14 15 16 17 18 19 |
# File 'lib/dav4rack/controller.rb', line 13 def initialize(request, response, ={}) raise Forbidden if request.path_info.include?('../') @request = request @response = response @options = @resource = resource_class.new(actual_path, implied_path, @request, @response, @options) end |
Instance Attribute Details
#request ⇒ Object (readonly)
Returns the value of attribute request.
6 7 8 |
# File 'lib/dav4rack/controller.rb', line 6 def request @request end |
#resource ⇒ Object (readonly)
Returns the value of attribute resource.
6 7 8 |
# File 'lib/dav4rack/controller.rb', line 6 def resource @resource end |
#response ⇒ Object (readonly)
Returns the value of attribute response.
6 7 8 |
# File 'lib/dav4rack/controller.rb', line 6 def response @response end |
Instance Method Details
#authenticate ⇒ Object
Perform authentication NOTE: Authentication will only be performed if the Resource has defined an #authenticate method
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/dav4rack/controller.rb', line 258 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
116 117 118 |
# File 'lib/dav4rack/controller.rb', line 116 def copy move(:copy) end |
#delete ⇒ Object
Return response to DELETE
94 95 96 97 98 99 100 101 |
# File 'lib/dav4rack/controller.rb', line 94 def delete if(resource.exist?) resource.lock_check resource.delete else NotFound end end |
#get ⇒ Object
Return response to GET
58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/dav4rack/controller.rb', line 58 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
46 47 48 49 50 51 52 53 54 55 |
# File 'lib/dav4rack/controller.rb', line 46 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.
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 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/dav4rack/controller.rb', line 199 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.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
104 105 106 107 108 109 110 111 112 113 |
# File 'lib/dav4rack/controller.rb', line 104 def mkcol resource.lock_check status = resource.make_collection multistatus do |xml| xml.response do xml.href "#{scheme}://#{host}:#{port}#{url_escape(resource.public_path)}" xml.status "#{http_version} #{status.status_line}" end 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)
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/dav4rack/controller.rb', line 123 def move(*args) unless(resource.exist?) NotFound else resource.lock_check unless 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 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}#{dest.public_path}" if status == Created multistatus do |xml| xml.response do xml.href "#{scheme}://#{host}:#{port}#{status == Created ? dest.public_path : resource.public_path}" xml.status "#{http_version} #{status.status_line}" end end end end end |
#options ⇒ Object
Return response to OPTIONS
38 39 40 41 42 43 |
# File 'lib/dav4rack/controller.rb', line 38 def 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 |
#post ⇒ Object
Return response to POST
89 90 91 |
# File 'lib/dav4rack/controller.rb', line 89 def post resource.post(request, response) end |
#propfind ⇒ Object
Return respoonse to PROPFIND
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/dav4rack/controller.rb', line 155 def propfind unless(resource.exist?) NotFound else unless(request_document.xpath("//#{ns}propfind/#{ns}allprop").empty?) names = resource.property_names else names = request_document.xpath("//#{ns}propfind/#{ns}prop").children.find_all{|n|n.element?}.map{|n|n.name} names = resource.property_names if names.empty? end multistatus do |xml| find_resources.each do |resource| xml.response do xml.href "#{scheme}://#{host}:#{port}#{url_escape(resource.public_path)}" propstats(xml, get_properties(resource, names)) end end end end end |
#proppatch ⇒ Object
Return response to PROPPATCH
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/dav4rack/controller.rb', line 177 def proppatch unless(resource.exist?) NotFound else resource.lock_check prop_rem = request_match('/propertyupdate/remove/prop').children.map{|n| [n.name] } prop_set = request_match('/propertyupdate/set/prop').children.map{|n| [n.name, n.text] } multistatus do |xml| find_resources.each do |resource| xml.response do xml.href "#{scheme}://#{host}:#{port}#{url_escape(resource.public_path)}" propstats(xml, set_properties(resource, prop_set)) end end end end end |
#put ⇒ Object
Return response to PUT
74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/dav4rack/controller.rb', line 74 def put if(resource.collection?) Forbidden elsif(!resource.parent_exists? || !resource.parent.collection?) Conflict else resource.lock_check status = resource.put(request, response) response['Location'] = "#{scheme}://#{host}:#{port}#{resource.public_path}" if status == Created response.body = response['Location'] status end end |
#unlock ⇒ Object
Unlock current resource
251 252 253 |
# File 'lib/dav4rack/controller.rb', line 251 def unlock resource.unlock(lock_token) end |
#url_escape(s) ⇒ Object
- s
-
string
Escape URL string
23 24 25 26 27 |
# File 'lib/dav4rack/controller.rb', line 23 def url_escape(s) s.gsub(/([^\/a-zA-Z0-9_.-]+)/n) do '%' + $1.unpack('H2' * $1.size).join('%').upcase end.tr(' ', '+') end |
#url_unescape(s) ⇒ Object
- s
-
string
Unescape URL string
31 32 33 34 35 |
# File 'lib/dav4rack/controller.rb', line 31 def url_unescape(s) s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do [$1.delete('%')].pack('H*') end end |