dav4rack 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -21,6 +21,10 @@ a pull request with your modifications. If you are just here to use the library,
21
21
  === Via RubyGems
22
22
 
23
23
  gem install dav4rack
24
+
25
+ == Documentation
26
+
27
+ * {DAV4Rack documentation}[http://chrisroberts.github.com/dav4rack]
24
28
 
25
29
  == Quickstart
26
30
 
@@ -90,9 +94,9 @@ lets continue with the last example but this time include the interceptor:
90
94
  end
91
95
  map '/' do
92
96
  use DAV4Rack::Interceptor, :mappings => {
93
- '/webdav/share/' => {:resource_class => FileResource, :custom => 'option'},
94
- '/webdav/share2/' => {:resource_class => CustomResource}
95
- }
97
+ '/webdav/share/' => {:resource_class => FileResource, :custom => 'option'},
98
+ '/webdav/share2/' => {:resource_class => CustomResource}
99
+ }
96
100
  use Rails::Rack::Static
97
101
  run ActionController::Dispatcher.new
98
102
  end
@@ -202,7 +206,7 @@ And if you don't have the X-Sendfile-Type header set, you can fix that by changi
202
206
 
203
207
  response.body = DAV4Rack::RemoteFile.new(item[:url], :size => content_length, :mime_type => content_type, :sendfile => 'X-Accel-Redirect', :sendfile_prefix => 'webdav_redirect')
204
208
 
205
- And if you have none of the above because your server hasn't been configured for sendfile support, your out of luck until it's configured.
209
+ And if you have none of the above because your server hasn't been configured for sendfile support, you're out of luck until it's configured.
206
210
 
207
211
  == Authentication
208
212
 
@@ -295,6 +299,13 @@ without getting stuck in a loop.
295
299
 
296
300
  Please use the issues at github: http://github.com/chrisroberts/dav4rack/issues
297
301
 
302
+ == Contributors
303
+
304
+ A big thanks to everyone contributing to help make this project better.
305
+
306
+ * {clyfe}[http://github.com/clyfe]
307
+ * {antiloopgmbh}[http://github.com/antiloopgmbh]
308
+
298
309
  == License
299
310
 
300
311
  Just like RackDAV before it, this software is distributed under the MIT license.
@@ -39,7 +39,7 @@
39
39
  response["Allow"] = 'OPTIONS,HEAD,GET,PUT,POST,DELETE,PROPFIND,PROPPATCH,MKCOL,COPY,MOVE,LOCK,UNLOCK'
40
40
  response["Dav"] = "2"
41
41
  response["Ms-Author-Via"] = "DAV"
42
- NoContent
42
+ OK
43
43
  end
44
44
 
45
45
  # Return response to HEAD
@@ -48,7 +48,7 @@
48
48
  response['Etag'] = resource.etag
49
49
  response['Content-Type'] = resource.content_type
50
50
  response['Last-Modified'] = resource.last_modified.httpdate
51
- NoContent
51
+ OK
52
52
  end
53
53
 
54
54
  # Return response to GET
@@ -127,8 +127,8 @@
127
127
  response['Location'] = "#{scheme}://#{host}:#{port}#{dest.public_path}" if status == Created
128
128
  multistatus do |xml|
129
129
  xml.response do
130
- xml.href "#{scheme}://#{host}:#{port}#{dest.public_path}"
131
- xml.status = "#{http_version} #{status.status_line}"
130
+ xml.href "#{scheme}://#{host}:#{port}#{status == Created ? dest.public_path : resource.public_path}"
131
+ xml.status "#{http_version} #{status.status_line}"
132
132
  end
133
133
  end
134
134
  end
@@ -202,6 +202,9 @@
202
202
  xml.locktoken do
203
203
  xml.href locktoken
204
204
  end
205
+ if(asked[:owner])
206
+ xml.owner asked[:owner]
207
+ end
205
208
  end
206
209
  end
207
210
  end
@@ -228,14 +231,18 @@
228
231
  # has defined an #authenticate method
229
232
  def authenticate
230
233
  authed = true
231
- if(resource.respond_to?(:authenticate))
234
+ if(resource.respond_to?(:authenticate, true))
232
235
  authed = false
236
+ uname = nil
237
+ password = nil
233
238
  if(request.env['HTTP_AUTHORIZATION'])
234
239
  auth = Rack::Auth::Basic::Request.new(request.env)
235
240
  if(auth.basic? && auth.credentials)
236
- authed = resource.authenticate(auth.credentials[0], auth.credentials[1])
241
+ uname = auth.credentials[0]
242
+ password = auth.credentials[1]
237
243
  end
238
244
  end
245
+ authed = resource.send(:authenticate, uname, password)
239
246
  end
240
247
  raise Unauthorized unless authed
241
248
  end
@@ -320,17 +327,17 @@
320
327
  end
321
328
 
322
329
  # Find resources at depth requested
323
- def find_resources
330
+ def find_resources(with_current_resource=true)
324
331
  ary = nil
325
332
  case depth
326
333
  when 0
327
- ary = [resource]
334
+ ary = []
328
335
  when 1
329
336
  ary = resource.children
330
337
  else
331
338
  ary = resource.descendants
332
339
  end
333
- ary ? ary : []
340
+ with_current_resource ? [resource] + ary : ary
334
341
  end
335
342
 
336
343
  # XML parsed request
@@ -6,10 +6,6 @@ module DAV4Rack
6
6
 
7
7
  include WEBrick::HTTPUtils
8
8
 
9
- before do |resource, method_name|
10
- resource.send(:check_authentication)
11
- end
12
-
13
9
  # If this is a collection, return the child resources.
14
10
  def children
15
11
  Dir[file_path + '/*'].map do |path|
@@ -84,7 +80,7 @@ module DAV4Rack
84
80
  # Save the content of the request.body.
85
81
  def put(request, response)
86
82
  write(request.body)
87
- Created
83
+ OK
88
84
  end
89
85
 
90
86
  # HTTP POST request.
@@ -99,7 +95,7 @@ module DAV4Rack
99
95
  # Delete this resource.
100
96
  def delete
101
97
  if stat.directory?
102
- Dir.rmdir(file_path)
98
+ FileUtils.rm_rf(file_path)
103
99
  else
104
100
  File.unlink(file_path)
105
101
  end
@@ -109,22 +105,31 @@ module DAV4Rack
109
105
  # HTTP COPY request.
110
106
  #
111
107
  # Copy this resource to given destination resource.
112
- def copy(dest)
113
- if stat.directory?
108
+ def copy(dest, overwrite = false)
109
+ if(dest.path == path)
110
+ Conflict
111
+ elsif(stat.directory?)
114
112
  dest.make_collection
113
+ FileUtils.cp_r("#{file_path}/.", "#{dest.send(:file_path)}/")
114
+ OK
115
115
  else
116
- open(file_path, "rb") do |file|
117
- dest.write(file)
116
+ exists = File.exists?(file_path)
117
+ if(exists && !overwrite)
118
+ PreconditionFailed
119
+ else
120
+ open(file_path, "rb") do |file|
121
+ dest.write(file)
122
+ end
123
+ exists ? NoContent : Created
118
124
  end
119
125
  end
120
- OK
121
126
  end
122
127
 
123
128
  # HTTP MOVE request.
124
129
  #
125
130
  # Move this resource to given destination resource.
126
- def move(dest)
127
- copy(dest)
131
+ def move(*args)
132
+ copy(*args)
128
133
  delete
129
134
  OK
130
135
  end
@@ -134,7 +139,7 @@ module DAV4Rack
134
139
  # Create this resource as collection.
135
140
  def make_collection
136
141
  Dir.mkdir(file_path)
137
- NoContent
142
+ Created
138
143
  end
139
144
 
140
145
  # Write to this resource from given IO.
@@ -154,21 +159,6 @@ module DAV4Rack
154
159
 
155
160
  private
156
161
 
157
- def check_authentication
158
- valid = true
159
- if(options[:username])
160
- valid = false
161
- if(request.env['HTTP_AUTHORIZATION'])
162
- auth = Rack::Auth::Basic::Request.new(request.env)
163
- if(auth.basic? && auth.credentials)
164
- valid = options[:username] == auth.credentials[0] && options[:password] == auth.credentials[1]
165
- end
166
- end
167
- end
168
- raise Unauthorized unless valid
169
- valid
170
- end
171
-
172
162
  def authenticate(user, pass)
173
163
  if(options[:username])
174
164
  options[:username] == user && options[:password] == pass
@@ -5,13 +5,15 @@ module DAV4Rack
5
5
  @roots = args[:mappings].keys
6
6
  @args = args
7
7
  @app = app
8
+ @intercept_methods = %w(OPTIONS PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK)
9
+ @intercept_methods -= args[:ignore_methods] if args[:ignore_methods]
8
10
  end
9
11
 
10
12
  def call(env)
11
13
  path = env['PATH_INFO'].downcase
12
14
  method = env['REQUEST_METHOD'].upcase
13
15
  app = nil
14
- if(@roots.detect{|x| path =~ /^#{Regexp.escape(x.downcase)}\/?/}.nil? && %w(OPTIONS PUT PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK).include?(method))
16
+ if(@roots.detect{|x| path =~ /^#{Regexp.escape(x.downcase)}\/?/}.nil? && @intercept_methods.include?(method))
15
17
  app = DAV4Rack::Handler.new(:resource_class => InterceptorResource, :mappings => @args[:mappings], :log_to => @args[:log_to])
16
18
  end
17
19
  app ? app.call(env) : @app.call(env)
@@ -196,14 +196,14 @@ module DAV4Rack
196
196
  # HTTP COPY request.
197
197
  #
198
198
  # Copy this resource to given destination resource.
199
- def copy(dest)
199
+ def copy(dest, overwrite=false)
200
200
  raise NotImplementedError
201
201
  end
202
202
 
203
203
  # HTTP MOVE request.
204
204
  #
205
205
  # Move this resource to given destination resource.
206
- def move(dest)
206
+ def move(dest, overwrite=false)
207
207
  raise NotImplemented
208
208
  end
209
209
 
@@ -287,7 +287,6 @@ module DAV4Rack
287
287
  raise Forbidden unless lock && lock.user == @user
288
288
  raise Conflict unless lock.path =~ /^#{Regexp.escape(@path)}.*$/
289
289
  lock.destroy
290
- delete if name[0,1] == '.' && @options[:delete_dotfiles]
291
290
  NoContent
292
291
  end
293
292
 
@@ -394,6 +393,7 @@ module DAV4Rack
394
393
  end
395
394
 
396
395
  # Does client allow GET redirection
396
+ # TODO: Get a comprehensive list in here. Especially now that trasmit added support
397
397
  def allows_redirect?
398
398
  %w(cyberduck konqueror).any?{|x| (request.respond_to?(:user_agent) ? request.user_agent.to_s.downcase : request.env['HTTP_USER_AGENT'].to_s.downcase) =~ /#{Regexp.escape(x)}/}
399
399
  end
@@ -1,3 +1,3 @@
1
1
  module DAV4Rack
2
- VERSION = '0.1.4'
2
+ VERSION = '0.1.5'
3
3
  end
data/spec/handler_spec.rb CHANGED
@@ -1,16 +1,17 @@
1
1
  $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
2
2
 
3
3
  require 'rubygems'
4
- require 'rack_dav'
4
+ require 'dav4rack'
5
5
  require 'fileutils'
6
+ require 'nokogiri'
6
7
 
7
- describe RackDAV::Handler do
8
+ describe DAV4Rack::Handler do
8
9
  DOC_ROOT = File.expand_path(File.dirname(__FILE__) + '/htdocs')
9
10
  METHODS = %w(GET PUT POST DELETE PROPFIND PROPPATCH MKCOL COPY MOVE OPTIONS HEAD LOCK UNLOCK)
10
11
 
11
12
  before do
12
13
  FileUtils.mkdir(DOC_ROOT) unless File.exists?(DOC_ROOT)
13
- @controller = RackDAV::Handler.new(:root => DOC_ROOT)
14
+ @controller = DAV4Rack::Handler.new(:root => DOC_ROOT)
14
15
  end
15
16
 
16
17
  after do
@@ -22,7 +23,7 @@ describe RackDAV::Handler do
22
23
  def request(method, uri, options={})
23
24
  options = {
24
25
  'HTTP_HOST' => 'localhost',
25
- 'REMOTE_USER' => 'manni'
26
+ 'REMOTE_USER' => 'user'
26
27
  }.merge(options)
27
28
  request = Rack::MockRequest.new(@controller)
28
29
  @response = request.request(method, uri, options)
@@ -34,13 +35,16 @@ describe RackDAV::Handler do
34
35
  end
35
36
  end
36
37
 
37
- def render
38
- xml = Builder::XmlMarkup.new
39
- xml.instruct! :xml, :version => "1.0", :encoding => "UTF-8"
40
- xml.namespace('d') do
41
- yield xml
38
+ def render(root_type)
39
+ raise ArgumentError.new 'Expecting block' unless block_given?
40
+ doc = Nokogiri::XML::Builder.new do |xml_base|
41
+ xml_base.send(root_type.to_s, 'xmlns:D' => 'D:') do
42
+ xml_base.parent.namespace = xml_base.parent.namespace_definitions.first
43
+ xml = xml_base['D']
44
+ yield xml
45
+ end
42
46
  end
43
- xml.target!
47
+ doc.to_xml
44
48
  end
45
49
 
46
50
  def url_escape(string)
@@ -50,22 +54,35 @@ describe RackDAV::Handler do
50
54
  end
51
55
 
52
56
  def response_xml
53
- REXML::Document.new(@response.body)
57
+ Nokogiri.XML(@response.body)
54
58
  end
55
59
 
56
60
  def multistatus_response(pattern)
57
61
  @response.should be_multi_status
58
- REXML::XPath::match(response_xml, "/multistatus/response", '' => 'DAV:').should_not be_empty
59
- REXML::XPath::match(response_xml, "/multistatus/response" + pattern, '' => 'DAV:')
62
+ response_xml.xpath('//D:multistatus/D:response', response_xml.root.namespaces).should_not be_empty
63
+ response_xml.xpath("//D:multistatus/D:response#{pattern}", response_xml.root.namespaces)
60
64
  end
61
65
 
66
+ def multi_status_created
67
+ response_xml.xpath('//D:multistatus/D:response/D:status').should_not be_empty
68
+ response_xml.xpath('//D:multistatus/D:response/D:status').text.should =~ /Created/
69
+ end
70
+
71
+ def multi_status_ok
72
+ response_xml.xpath('//D:multistatus/D:response/D:status').should_not be_empty
73
+ response_xml.xpath('//D:multistatus/D:response/D:status').text.should =~ /OK/
74
+ end
75
+
76
+ def multi_status_no_content
77
+ response_xml.xpath('//D:multistatus/D:response/D:status').should_not be_empty
78
+ response_xml.xpath('//D:multistatus/D:response/D:status').text.should =~ /No Content/
79
+ end
80
+
62
81
  def propfind_xml(*props)
63
- render do |xml|
64
- xml.propfind('xmlns:d' => "DAV:") do
65
- xml.prop do
66
- props.each do |prop|
67
- xml.tag! prop
68
- end
82
+ render(:propfind) do |xml|
83
+ xml.prop do
84
+ props.each do |prop|
85
+ xml.send(prop.to_sym)
69
86
  end
70
87
  end
71
88
  end
@@ -80,7 +97,8 @@ describe RackDAV::Handler do
80
97
  end
81
98
 
82
99
  it 'should return headers' do
83
- put('/test.html', :input => '<html/>').should be_ok
100
+ put('/test.html', :input => '<html/>')
101
+ multi_status_ok.should eq true
84
102
  head('/test.html').should be_ok
85
103
 
86
104
  response.headers['etag'].should_not be_nil
@@ -97,25 +115,31 @@ describe RackDAV::Handler do
97
115
  end
98
116
 
99
117
  it 'should create a resource and allow its retrieval' do
100
- put('/test', :input => 'body').should be_ok
118
+ put('/test', :input => 'body')
119
+ multi_status_ok.should eq true
101
120
  get('/test').should be_ok
102
121
  response.body.should == 'body'
103
122
  end
104
123
  it 'should create and find a url with escaped characters' do
105
- put(url_escape('/a b'), :input => 'body').should be_ok
124
+ put(url_escape('/a b'), :input => 'body')
125
+ multi_status_ok.should eq true
106
126
  get(url_escape('/a b')).should be_ok
107
127
  response.body.should == 'body'
108
128
  end
109
129
 
110
130
  it 'should delete a single resource' do
111
- put('/test', :input => 'body').should be_ok
131
+ put('/test', :input => 'body')
132
+ multi_status_ok.should eq true
112
133
  delete('/test').should be_no_content
113
134
  end
114
135
 
115
136
  it 'should delete recursively' do
116
- mkcol('/folder').should be_created
117
- put('/folder/a', :input => 'body').should be_ok
118
- put('/folder/b', :input => 'body').should be_ok
137
+ mkcol('/folder')
138
+ multi_status_created.should eq true
139
+ put('/folder/a', :input => 'body')
140
+ multi_status_ok.should eq true
141
+ put('/folder/b', :input => 'body')
142
+ multi_status_ok.should eq true
119
143
 
120
144
  delete('/folder').should be_no_content
121
145
  get('/folder').should be_not_found
@@ -124,79 +148,94 @@ describe RackDAV::Handler do
124
148
  end
125
149
 
126
150
  it 'should not allow copy to another domain' do
127
- put('/test', :input => 'body').should be_ok
151
+ put('/test', :input => 'body')
152
+ multi_status_ok.should eq true
128
153
  copy('http://localhost/', 'HTTP_DESTINATION' => 'http://another/').should be_bad_gateway
129
154
  end
130
155
 
131
156
  it 'should not allow copy to the same resource' do
132
- put('/test', :input => 'body').should be_ok
157
+ put('/test', :input => 'body')
158
+ multi_status_ok.should eq true
133
159
  copy('/test', 'HTTP_DESTINATION' => '/test').should be_forbidden
134
160
  end
135
161
 
136
- it 'should not allow an invalid destination uri' do
137
- put('/test', :input => 'body').should be_ok
138
- copy('/test', 'HTTP_DESTINATION' => '%').should be_bad_request
139
- end
140
-
141
162
  it 'should copy a single resource' do
142
- put('/test', :input => 'body').should be_ok
143
- copy('/test', 'HTTP_DESTINATION' => '/copy').should be_created
163
+ put('/test', :input => 'body')
164
+ multi_status_ok.should eq true
165
+ copy('/test', 'HTTP_DESTINATION' => '/copy')
166
+ multi_status_no_content.should eq true
144
167
  get('/copy').body.should == 'body'
145
168
  end
146
169
 
147
170
  it 'should copy a resource with escaped characters' do
148
- put(url_escape('/a b'), :input => 'body').should be_ok
149
- copy(url_escape('/a b'), 'HTTP_DESTINATION' => url_escape('/a c')).should be_created
171
+ put(url_escape('/a b'), :input => 'body')
172
+ multi_status_ok.should eq true
173
+ copy(url_escape('/a b'), 'HTTP_DESTINATION' => url_escape('/a c'))
174
+ multi_status_no_content.should eq true
150
175
  get(url_escape('/a c')).should be_ok
151
176
  response.body.should == 'body'
152
177
  end
153
178
 
154
179
  it 'should deny a copy without overwrite' do
155
- put('/test', :input => 'body').should be_ok
156
- put('/copy', :input => 'copy').should be_ok
180
+ put('/test', :input => 'body')
181
+ multi_status_ok.should eq true
182
+ put('/copy', :input => 'copy')
183
+ multi_status_ok.should eq true
157
184
  copy('/test', 'HTTP_DESTINATION' => '/copy', 'HTTP_OVERWRITE' => 'F')
158
185
 
159
- multistatus_response('/href').first.text.should == 'http://localhost/test'
160
- multistatus_response('/status').first.text.should match(/412 Precondition Failed/)
186
+ multistatus_response('/D:href').first.text.should =~ /http:\/\/localhost(:\d+)?\/test/
187
+ multistatus_response('/D:status').first.text.should match(/412 Precondition Failed/)
161
188
 
162
189
  get('/copy').body.should == 'copy'
163
190
  end
164
191
 
165
192
  it 'should allow a copy with overwrite' do
166
- put('/test', :input => 'body').should be_ok
167
- put('/copy', :input => 'copy').should be_ok
168
- copy('/test', 'HTTP_DESTINATION' => '/copy', 'HTTP_OVERWRITE' => 'T').should be_no_content
193
+ put('/test', :input => 'body')
194
+ multi_status_ok.should eq true
195
+ put('/copy', :input => 'copy')
196
+ multi_status_ok.should eq true
197
+ copy('/test', 'HTTP_DESTINATION' => '/copy', 'HTTP_OVERWRITE' => 'T')
198
+ multi_status_no_content.should eq true
169
199
  get('/copy').body.should == 'body'
170
200
  end
171
201
 
172
- it 'should copy a collection' do
173
- mkcol('/folder').should be_created
174
- copy('/folder', 'HTTP_DESTINATION' => '/copy').should be_created
202
+ it 'should copy a collection' do
203
+ mkcol('/folder')
204
+ multi_status_created.should eq true
205
+ copy('/folder', 'HTTP_DESTINATION' => '/copy')
206
+ multi_status_ok.should eq true
175
207
  propfind('/copy', :input => propfind_xml(:resourcetype))
176
- multistatus_response('/propstat/prop/resourcetype/collection').should_not be_empty
208
+ multistatus_response('/D:propstat/D:prop/D:resourcetype/D:collection').should_not be_empty
177
209
  end
178
210
 
179
211
  it 'should copy a collection resursively' do
180
- mkcol('/folder').should be_created
181
- put('/folder/a', :input => 'A').should be_ok
182
- put('/folder/b', :input => 'B').should be_ok
212
+ mkcol('/folder')
213
+ multi_status_created.should eq true
214
+ put('/folder/a', :input => 'A')
215
+ multi_status_ok.should eq true
216
+ put('/folder/b', :input => 'B')
217
+ multi_status_ok.should eq true
183
218
 
184
- copy('/folder', 'HTTP_DESTINATION' => '/copy').should be_created
219
+ copy('/folder', 'HTTP_DESTINATION' => '/copy')
220
+ multi_status_ok.should eq true
185
221
  propfind('/copy', :input => propfind_xml(:resourcetype))
186
- multistatus_response('/propstat/prop/resourcetype/collection').should_not be_empty
187
-
222
+ multistatus_response('/D:propstat/D:prop/D:resourcetype/D:collection').should_not be_empty
188
223
  get('/copy/a').body.should == 'A'
189
224
  get('/copy/b').body.should == 'B'
190
225
  end
191
226
 
192
227
  it 'should move a collection recursively' do
193
- mkcol('/folder').should be_created
194
- put('/folder/a', :input => 'A').should be_ok
195
- put('/folder/b', :input => 'B').should be_ok
228
+ mkcol('/folder')
229
+ multi_status_created.should eq true
230
+ put('/folder/a', :input => 'A')
231
+ multi_status_ok.should eq true
232
+ put('/folder/b', :input => 'B')
233
+ multi_status_ok.should eq true
196
234
 
197
- move('/folder', 'HTTP_DESTINATION' => '/move').should be_created
235
+ move('/folder', 'HTTP_DESTINATION' => '/move')
236
+ multi_status_ok.should eq true
198
237
  propfind('/move', :input => propfind_xml(:resourcetype))
199
- multistatus_response('/propstat/prop/resourcetype/collection').should_not be_empty
238
+ multistatus_response('/D:propstat/D:prop/D:resourcetype/D:collection').should_not be_empty
200
239
 
201
240
  get('/move/a').body.should == 'A'
202
241
  get('/move/b').body.should == 'B'
@@ -205,9 +244,10 @@ describe RackDAV::Handler do
205
244
  end
206
245
 
207
246
  it 'should create a collection' do
208
- mkcol('/folder').should be_created
247
+ mkcol('/folder')
248
+ multi_status_created.should eq true
209
249
  propfind('/folder', :input => propfind_xml(:resourcetype))
210
- multistatus_response('/propstat/prop/resourcetype/collection').should_not be_empty
250
+ multistatus_response('/D:propstat/D:prop/D:resourcetype/D:collection').should_not be_empty
211
251
  end
212
252
 
213
253
  it 'should not find properties for nonexistent resources' do
@@ -215,56 +255,54 @@ describe RackDAV::Handler do
215
255
  end
216
256
 
217
257
  it 'should find all properties' do
218
- xml = render do |xml|
219
- xml.propfind('xmlns:d' => "DAV:") do
220
- xml.allprop
221
- end
258
+ xml = render(:propfind) do |xml|
259
+ xml.allprop
222
260
  end
223
261
 
224
262
  propfind('http://localhost/', :input => xml)
225
263
 
226
- multistatus_response('/href').first.text.strip.should == 'http://localhost/'
264
+ multistatus_response('/D:href').first.text.strip.should =~ /http:\/\/localhost(:\d+)?\//
227
265
 
228
266
  props = %w(creationdate displayname getlastmodified getetag resourcetype getcontenttype getcontentlength)
229
267
  props.each do |prop|
230
- multistatus_response('/propstat/prop/' + prop).should_not be_empty
268
+ multistatus_response("/D:propstat/D:prop/D:#{prop}").should_not be_empty
231
269
  end
232
270
  end
233
271
 
234
272
  it 'should find named properties' do
235
- put('/test.html', :input => '<html/>').should be_ok
273
+ put('/test.html', :input => '<html/>')
274
+ multi_status_ok.should eq true
236
275
  propfind('/test.html', :input => propfind_xml(:getcontenttype, :getcontentlength))
237
276
 
238
- multistatus_response('/propstat/prop/getcontenttype').first.text.should == 'text/html'
239
- multistatus_response('/propstat/prop/getcontentlength').first.text.should == '7'
277
+ multistatus_response('/D:propstat/D:prop/D:getcontenttype').first.text.should == 'text/html'
278
+ multistatus_response('/D:propstat/D:prop/D:getcontentlength').first.text.should == '7'
240
279
  end
241
280
 
242
281
  it 'should lock a resource' do
243
- put('/test', :input => 'body').should be_ok
282
+ put('/test', :input => 'body')
283
+ multi_status_ok.should eq true
244
284
 
245
- xml = render do |xml|
246
- xml.lockinfo('xmlns:d' => "DAV:") do
247
- xml.lockscope { xml.exclusive }
248
- xml.locktype { xml.write }
249
- xml.owner { xml.href "http://test.de/" }
250
- end
285
+ xml = render(:lockinfo) do |xml|
286
+ xml.lockscope { xml.exclusive }
287
+ xml.locktype { xml.write }
288
+ xml.owner { xml.href "http://test.de/" }
251
289
  end
252
290
 
253
291
  lock('/test', :input => xml)
254
292
 
255
293
  response.should be_ok
256
-
294
+
257
295
  match = lambda do |pattern|
258
- REXML::XPath::match(response_xml, "/prop/lockdiscovery/activelock" + pattern, '' => 'DAV:')
296
+ response_xml.xpath "/D:prop/D:lockdiscovery/D:activelock#{pattern}"
259
297
  end
260
298
 
261
299
  match[''].should_not be_empty
262
300
 
263
- match['/locktype'].should_not be_empty
264
- match['/lockscope'].should_not be_empty
265
- match['/depth'].should_not be_empty
266
- match['/owner'].should_not be_empty
267
- match['/timeout'].should_not be_empty
268
- match['/locktoken'].should_not be_empty
301
+ match['/D:locktype'].should_not be_empty
302
+ match['/D:lockscope'].should_not be_empty
303
+ match['/D:depth'].should_not be_empty
304
+ match['/D:timeout'].should_not be_empty
305
+ match['/D:locktoken'].should_not be_empty
306
+ match['/D:owner'].should_not be_empty
269
307
  end
270
308
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dav4rack
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 4
10
- version: 0.1.4
9
+ - 5
10
+ version: 0.1.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Chris Roberts
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-10-22 00:00:00 -07:00
18
+ date: 2010-11-04 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency