dav4rack 0.2.10 → 0.2.11

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.
@@ -311,6 +311,8 @@ A big thanks to everyone contributing to help make this project better.
311
311
  * {doxavore}[https://github.com/doxavore]
312
312
  * {spicyj}[https://github.com/spicyj]
313
313
  * {TurchenkoAlex}[https://github.com/TurchenkoAlex]
314
+ * {exabugs}[https://github.com/exabugs]
315
+ * {inferiorhumanorgans}[https://github.com/inferiorhumanorgans]
314
316
 
315
317
  == License
316
318
 
@@ -27,7 +27,8 @@ opts = GetoptLong.new(
27
27
  ['--version', '-v', GetoptLong::NO_ARGUMENT],
28
28
  ['--root', '-r', GetoptLong::REQUIRED_ARGUMENT],
29
29
  ['--log', '-l', GetoptLong::OPTIONAL_ARGUMENT],
30
- ['--verbosity', '-V', GetoptLong::REQUIRED_ARGUMENT]
30
+ ['--verbosity', '-V', GetoptLong::REQUIRED_ARGUMENT],
31
+ ['--pretty-xml', '-P', GetoptLong::REQUIRED_ARGUMENT]
31
32
  )
32
33
 
33
34
  credentials = {}
@@ -47,6 +48,8 @@ opts.each do |opt,arg|
47
48
  puts "ERROR: Path provided is not a valid directory (#{arg})"
48
49
  exit(-1)
49
50
  end
51
+ when '--pretty-xml'
52
+ credentials[:pretty_xml] = true
50
53
  when '--version'
51
54
  print_version_info
52
55
  exit(0)
@@ -1,3 +1,5 @@
1
+ require 'uri'
2
+
1
3
  module DAV4Rack
2
4
 
3
5
  class Controller
@@ -11,7 +13,7 @@ module DAV4Rack
11
13
  # Create a new Controller.
12
14
  # NOTE: options will be passed to Resource
13
15
  def initialize(request, response, options={})
14
- raise Forbidden if request.path_info.include?('../')
16
+ raise Forbidden if request.path_info.include?('..')
15
17
  @request = request
16
18
  @response = response
17
19
  @options = options
@@ -20,18 +22,18 @@ module DAV4Rack
20
22
 
21
23
  # s:: string
22
24
  # Escape URL string
23
- def url_escape(s)
24
- s.gsub(/([^\/a-zA-Z0-9_.-]+)/n) do
25
- '%' + $1.unpack('H2' * $1.size).join('%').upcase
26
- end.tr(' ', '+')
25
+ def url_format(resource)
26
+ ret = URI.escape(resource.public_path)
27
+ if resource.collection? and ret[-1,1] != '/'
28
+ ret += '/'
29
+ end
30
+ ret
27
31
  end
28
32
 
29
33
  # s:: string
30
34
  # Unescape URL string
31
35
  def url_unescape(s)
32
- s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n) do
33
- [$1.delete('%')].pack('H*')
34
- end
36
+ URI.unescape(s)
35
37
  end
36
38
 
37
39
  # Return response to OPTIONS
@@ -79,7 +81,7 @@ module DAV4Rack
79
81
  else
80
82
  resource.lock_check
81
83
  status = resource.put(request, response)
82
- response['Location'] = "#{scheme}://#{host}:#{port}#{resource.public_path}" if status == Created
84
+ response['Location'] = "#{scheme}://#{host}:#{port}#{url_format(resource)}" if status == Created
83
85
  response.body = response['Location']
84
86
  status
85
87
  end
@@ -104,11 +106,17 @@ module DAV4Rack
104
106
  def mkcol
105
107
  resource.lock_check
106
108
  status = resource.make_collection
107
- multistatus do |xml|
108
- xml.response do
109
- xml.href "#{scheme}://#{host}:#{port}#{url_escape(resource.public_path)}"
110
- xml.status "#{http_version} #{status.status_line}"
109
+ gen_url = "#{scheme}://#{host}:#{port}#{url_format(resource)}" if status == Created
110
+ if(resource.use_compat_mkcol_response?)
111
+ multistatus do |xml|
112
+ xml.response do
113
+ xml.href gen_url
114
+ xml.status "#{http_version} #{status.status_line}"
115
+ end
111
116
  end
117
+ else
118
+ response['Location'] = gen_url
119
+ status
112
120
  end
113
121
  end
114
122
 
@@ -132,6 +140,7 @@ module DAV4Rack
132
140
  elsif(destination == resource.public_path)
133
141
  Forbidden
134
142
  else
143
+ collection = resource.collection?
135
144
  dest = resource_class.new(destination, clean_path(destination), @request, @response, @options.merge(:user => resource.user))
136
145
  status = nil
137
146
  if(args.include?(:copy))
@@ -140,12 +149,17 @@ module DAV4Rack
140
149
  return Conflict unless depth.is_a?(Symbol) || depth > 1
141
150
  status = resource.move(dest, overwrite)
142
151
  end
143
- response['Location'] = "#{scheme}://#{host}:#{port}#{dest.public_path}" if status == Created
144
- multistatus do |xml|
145
- xml.response do
146
- xml.href "#{scheme}://#{host}:#{port}#{status == Created ? dest.public_path : resource.public_path}"
147
- xml.status "#{http_version} #{status.status_line}"
152
+ response['Location'] = "#{scheme}://#{host}:#{port}#{url_format(dest)}" if status == Created
153
+ # RFC 2518
154
+ if collection
155
+ multistatus do |xml|
156
+ xml.response do
157
+ xml.href "#{scheme}://#{host}:#{port}#{url_format(status == Created ? dest : resource)}"
158
+ xml.status "#{http_version} #{status.status_line}"
159
+ end
148
160
  end
161
+ else
162
+ status
149
163
  end
150
164
  end
151
165
  end
@@ -159,13 +173,26 @@ module DAV4Rack
159
173
  unless(request_document.xpath("//#{ns}propfind/#{ns}allprop").empty?)
160
174
  names = resource.property_names
161
175
  else
162
- names = request_document.xpath("//#{ns}propfind/#{ns}prop").children.find_all{|n|n.element?}.map{|n|n.name}
176
+ names = (
177
+ ns.empty? ? request_document.remove_namespaces! : request_document
178
+ ).xpath(
179
+ "//#{ns}propfind/#{ns}prop"
180
+ ).children.find_all{ |item|
181
+ item.element? && item.name.start_with?(ns)
182
+ }.map{ |item|
183
+ item.name.sub("#{ns}::", '')
184
+ }
185
+ raise BadRequest if names.empty?
163
186
  names = resource.property_names if names.empty?
164
187
  end
165
188
  multistatus do |xml|
166
189
  find_resources.each do |resource|
167
190
  xml.response do
168
- xml.href "#{scheme}://#{host}:#{port}#{url_escape(resource.public_path)}"
191
+ unless(resource.propstat_relative_path)
192
+ xml.href "#{scheme}://#{host}:#{port}#{url_format(resource)}"
193
+ else
194
+ xml.href url_format(resource)
195
+ end
169
196
  propstats(xml, get_properties(resource, names))
170
197
  end
171
198
  end
@@ -184,7 +211,7 @@ module DAV4Rack
184
211
  multistatus do |xml|
185
212
  find_resources.each do |resource|
186
213
  xml.response do
187
- xml.href "#{scheme}://#{host}:#{port}#{url_escape(resource.public_path)}"
214
+ xml.href "#{scheme}://#{host}:#{port}#{url_format(resource)}"
188
215
  propstats(xml, set_properties(resource, prop_set))
189
216
  end
190
217
  end
@@ -386,9 +413,9 @@ module DAV4Rack
386
413
 
387
414
  # pattern:: XPath pattern
388
415
  # Search XML document for given XPath
416
+ # TODO: Stripping namespaces not so great
389
417
  def request_match(pattern)
390
- nil unless request_document
391
- request_document.xpath(pattern, request_document.root.namespaces)
418
+ request_document.remove_namespaces!.xpath(pattern, request_document.root.namespaces)
392
419
  end
393
420
 
394
421
  # root_type:: Root tag name
@@ -396,14 +423,20 @@ module DAV4Rack
396
423
  def render_xml(root_type)
397
424
  raise ArgumentError.new 'Expecting block' unless block_given?
398
425
  doc = Nokogiri::XML::Builder.new do |xml_base|
399
- xml_base.send(root_type.to_s, 'xmlns:D' => 'DAV:') do
426
+ xml_base.send(root_type.to_s, {'xmlns:D' => 'DAV:'}.merge(resource.root_xml_attributes)) do
400
427
  xml_base.parent.namespace = xml_base.parent.namespace_definitions.first
401
428
  xml = xml_base['D']
402
429
  yield xml
403
430
  end
404
431
  end
405
-
406
- response.body = doc.to_xml
432
+
433
+ if(@options[:pretty_xml])
434
+ response.body = doc.to_xml
435
+ else
436
+ response.body = doc.to_xml(
437
+ :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML
438
+ )
439
+ end
407
440
  response["Content-Type"] = 'text/xml; charset="utf-8"'
408
441
  response["Content-Length"] = response.body.size.to_s
409
442
  end
@@ -422,7 +455,7 @@ module DAV4Rack
422
455
  def response_errors(xml, errors)
423
456
  for path, status in errors
424
457
  xml.response do
425
- xml.href "#{scheme}://#{host}:#{port}#{path}"
458
+ xml.href "#{scheme}://#{host}:#{port}#{URI.escape(path)}"
426
459
  xml.status "#{http_version} #{status.status_line}"
427
460
  end
428
461
  end
@@ -440,7 +473,7 @@ module DAV4Rack
440
473
  rescue Unauthorized => u
441
474
  raise u
442
475
  rescue Status
443
- stats[$!] << name
476
+ stats[$!.class] << name
444
477
  end
445
478
  end
446
479
  stats
@@ -457,7 +490,7 @@ module DAV4Rack
457
490
  rescue Unauthorized => u
458
491
  raise u
459
492
  rescue Status
460
- stats[$!] << name
493
+ stats[$!.class] << name
461
494
  end
462
495
  end
463
496
  stats
@@ -472,7 +505,9 @@ module DAV4Rack
472
505
  xml.propstat do
473
506
  xml.prop do
474
507
  for name, value in props
475
- if(value.is_a?(Nokogiri::XML::Node))
508
+ if(value.is_a?(Nokogiri::XML::DocumentFragment))
509
+ xml.__send__ :insert, value
510
+ elsif(value.is_a?(Nokogiri::XML::Node))
476
511
  xml.send(name) do
477
512
  xml_convert(xml, value)
478
513
  end
@@ -105,41 +105,71 @@ module DAV4Rack
105
105
  # HTTP COPY request.
106
106
  #
107
107
  # Copy this resource to given destination resource.
108
- def copy(dest, overwrite = false)
109
- if(dest.path == path)
110
- Conflict
111
- elsif(stat.directory?)
112
- dest.make_collection
113
- FileUtils.cp_r("#{file_path}/.", "#{dest.send(:file_path)}/")
114
- OK
108
+ # Copy this resource to given destination resource.
109
+ def copy(dest, overwrite)
110
+ if(collection?)
111
+ if(dest.exist?)
112
+ if(dest.collection? && overwrite)
113
+ FileUtils.cp_r(file_path, dest.send(:file_path))
114
+ Created
115
+ else
116
+ if(overwrite)
117
+ FileUtils.rm(dest.send(:file_path))
118
+ FileUtils.cp_r(file_path, dest.send(:file_path))
119
+ NoContent
120
+ else
121
+ PreconditionFailed
122
+ end
123
+ end
124
+ else
125
+ FileUtils.cp_r(file_path, dest.send(:file_path))
126
+ Created
127
+ end
115
128
  else
116
- exists = File.exists?(file_path)
117
- if(exists && !overwrite)
129
+ if(dest.exist? && !overwrite)
118
130
  PreconditionFailed
119
131
  else
120
- open(file_path, "rb") do |file|
121
- dest.write(file)
132
+ if(File.directory?(File.dirname(dest.send(:file_path))))
133
+ new = !dest.exist?
134
+ if(dest.collection? && dest.exist?)
135
+ FileUtils.rm_rf(dest.send(:file_path))
136
+ end
137
+ FileUtils.cp(file_path, dest.send(:file_path).sub(/\/$/, ''))
138
+ new ? Created : NoContent
139
+ else
140
+ Conflict
122
141
  end
123
- exists ? NoContent : Created
124
142
  end
125
143
  end
126
144
  end
127
-
145
+
128
146
  # HTTP MOVE request.
129
147
  #
130
148
  # Move this resource to given destination resource.
131
149
  def move(*args)
132
- copy(*args)
133
- delete
134
- OK
150
+ result = copy(*args)
151
+ delete if [Created, NoContent].include?(result)
152
+ result
135
153
  end
136
154
 
137
155
  # HTTP MKCOL request.
138
156
  #
139
157
  # Create this resource as collection.
140
158
  def make_collection
141
- Dir.mkdir(file_path)
142
- Created
159
+ if(request.body.read.to_s == '')
160
+ if(File.directory?(file_path))
161
+ MethodNotAllowed
162
+ else
163
+ if(File.directory?(File.dirname(file_path)))
164
+ Dir.mkdir(file_path)
165
+ Created
166
+ else
167
+ Conflict
168
+ end
169
+ end
170
+ else
171
+ UnsupportedMediaType
172
+ end
143
173
  end
144
174
 
145
175
  # Write to this resource from given IO.
@@ -157,7 +187,50 @@ module DAV4Rack
157
187
  File.unlink(tempfile) rescue nil
158
188
  end
159
189
 
160
- private
190
+ # name:: String - Property name
191
+ # Returns the value of the given property
192
+ def get_property(name)
193
+ super || custom_props(name)
194
+ end
195
+
196
+ # name:: String - Property name
197
+ # value:: New value
198
+ # Set the property to the given value
199
+ def set_property(name, value)
200
+ super || set_custom_props(name,value)
201
+ end
202
+
203
+ protected
204
+
205
+ def set_custom_props(key,val)
206
+ prop_hash[key.to_sym] = val
207
+ File.open(prop_path, 'w') do |file|
208
+ file.write(YAML.dump(prop_hash))
209
+ end
210
+ end
211
+
212
+ def custom_props(key)
213
+ prop_hash[key.to_sym]
214
+ end
215
+
216
+ def prop_path
217
+ path = File.join(root, '.props', File.dirname(file_path), File.basename(file_path))
218
+ unless(File.directory?(File.dirname(path)))
219
+ FileUtils.mkdir_p(File.dirname(path))
220
+ end
221
+ path
222
+ end
223
+
224
+ def prop_hash
225
+ unless(@_prop_hash)
226
+ if(File.exists?(prop_path))
227
+ @_prop_hash = YAML.load(File.read(prop_path))
228
+ else
229
+ @_prop_hash = {}
230
+ end
231
+ end
232
+ @_prop_hash
233
+ end
161
234
 
162
235
  def authenticate(user, pass)
163
236
  if(options[:username])
@@ -172,7 +245,7 @@ module DAV4Rack
172
245
  end
173
246
 
174
247
  def file_path
175
- root + '/' + path
248
+ File.join(root, path)
176
249
  end
177
250
 
178
251
  def stat
@@ -24,7 +24,8 @@ module DAV4Rack
24
24
 
25
25
  controller = nil
26
26
  begin
27
- controller = Controller.new(request, response, @options.dup)
27
+ controller_class = @options[:controller_class] || Controller
28
+ controller = controller_class.new(request, response, @options.dup)
28
29
  controller.authenticate
29
30
  res = controller.send(request.request_method.downcase)
30
31
  response.status = res.code if res.respond_to?(:code)
@@ -16,7 +16,8 @@ module DAV4Rack
16
16
  end
17
17
 
18
18
  class Resource
19
- attr_reader :path, :options, :public_path, :request, :response
19
+ attr_reader :path, :options, :public_path, :request,
20
+ :response, :propstat_relative_path, :root_xml_attributes
20
21
  attr_accessor :user
21
22
  @@blocks = {}
22
23
 
@@ -71,6 +72,8 @@ module DAV4Rack
71
72
  ]
72
73
  @public_path = public_path.dup
73
74
  @path = path.dup
75
+ @propstat_relative_path = !!options.delete(:propstat_relative_path)
76
+ @root_xml_attributes = options.delete(:root_xml_attributes) || {}
74
77
  @request = request
75
78
  @response = response
76
79
  unless(options.has_key?(:lock_class))
@@ -137,22 +140,23 @@ module DAV4Rack
137
140
 
138
141
  # Return the creation time.
139
142
  def creation_date
140
- NotImplemented
143
+ raise NotImplemented
141
144
  end
142
145
 
143
146
  # Return the time of last modification.
144
147
  def last_modified
145
- NotImplemented
148
+ raise NotImplemented
146
149
  end
147
150
 
148
151
  # Set the time of last modification.
149
152
  def last_modified=(time)
150
- NotImplemented
153
+ # Is this correct?
154
+ raise NotImplemented
151
155
  end
152
156
 
153
157
  # Return an Etag, an unique hash value for this resource.
154
158
  def etag
155
- NotImplemented
159
+ raise NotImplemented
156
160
  end
157
161
 
158
162
  # Return the resource type. Generally only used to specify
@@ -163,12 +167,12 @@ module DAV4Rack
163
167
 
164
168
  # Return the mime type of this resource.
165
169
  def content_type
166
- NotImplemented
170
+ raise NotImplemented
167
171
  end
168
172
 
169
173
  # Return the size in bytes for this resource.
170
174
  def content_length
171
- NotImplemented
175
+ raise NotImplemented
172
176
  end
173
177
 
174
178
  # HTTP GET request.
@@ -347,7 +351,7 @@ module DAV4Rack
347
351
  case name
348
352
  when 'resourcetype' then resource_type
349
353
  when 'displayname' then display_name
350
- when 'creationdate' then creation_date.xmlschema
354
+ when 'creationdate' then use_ms_compat_creationdate? ? creation_date.httpdate : creation_date.xmlschema
351
355
  when 'getcontentlength' then content_length.to_s
352
356
  when 'getcontenttype' then content_type
353
357
  when 'getetag' then etag
@@ -365,8 +369,6 @@ module DAV4Rack
365
369
  when 'getetag' then self.etag = value
366
370
  when 'getlastmodified' then self.last_modified = Time.httpdate(value)
367
371
  end
368
- rescue ArgumentError
369
- Conflict
370
372
  end
371
373
 
372
374
  # name:: Property name
@@ -390,9 +392,17 @@ module DAV4Rack
390
392
 
391
393
  # Return parent of this resource
392
394
  def parent
393
- elements = @path.scan(/[^\/]+/)
394
- return nil if elements.empty?
395
- self.class.new(('/' + @public_path.scan(/[^\/]+/)[0..-2].join('/')), ('/' + elements[0..-2].to_a.join('/')), @request, @response, @options.merge(:user => @user))
395
+ unless(@path.to_s.empty?)
396
+ self.class.new(
397
+ File.split(@public_path).first,
398
+ File.split(@path).first,
399
+ @request,
400
+ @response,
401
+ @options.merge(
402
+ :user => @user
403
+ )
404
+ )
405
+ end
396
406
  end
397
407
 
398
408
  # Return list of descendants
@@ -405,8 +415,6 @@ module DAV4Rack
405
415
  list
406
416
  end
407
417
 
408
- protected
409
-
410
418
  # Index page template for GETs on collection
411
419
  def index_page
412
420
  '<html><head> <title>%s</title>
@@ -425,10 +433,30 @@ module DAV4Rack
425
433
  %r{cyberduck}i,
426
434
  %r{konqueror}i
427
435
  ].any? do |regexp|
428
- (request.respond_to?(:user_agent) ? request.user_agent : request.env['HTTP_USER_AGENT']) =~ regexp
436
+ (request.respond_to?(:user_agent) ? request.user_agent : request.env['HTTP_USER_AGENT']).to_s =~ regexp
429
437
  end
430
438
  end
431
-
439
+
440
+ def use_compat_mkcol_response?
441
+ @options[:compat_mkcol] || @options[:compat_all]
442
+ end
443
+
444
+ # Returns true if using an MS client
445
+ def use_ms_compat_creationdate?
446
+ if(@options[:compat_ms_mangled_creationdate] || @options[:compat_all])
447
+ is_ms_client?
448
+ end
449
+ end
450
+
451
+ # Basic user agent testing for MS authored client
452
+ def is_ms_client?
453
+ [%r{microsoft-webdav}i, %r{microsoft office}i].any? do |regexp|
454
+ (request.respond_to?(:user_agent) ? request.user_agent : request.env['HTTP_USER_AGENT']).to_s =~ regexp
455
+ end
456
+ end
457
+
458
+ protected
459
+
432
460
  # Returns authentication credentials if available in form of [username,password]
433
461
  # TODO: Add support for digest
434
462
  def auth_credentials
@@ -13,5 +13,5 @@ module DAV4Rack
13
13
  end
14
14
  end
15
15
 
16
- VERSION = Version.new('0.2.10')
16
+ VERSION = Version.new('0.2.11')
17
17
  end
@@ -4,6 +4,7 @@ require 'rubygems'
4
4
  require 'dav4rack'
5
5
  require 'fileutils'
6
6
  require 'nokogiri'
7
+ require 'rspec'
7
8
 
8
9
  describe DAV4Rack::Handler do
9
10
  DOC_ROOT = File.expand_path(File.dirname(__FILE__) + '/htdocs')
@@ -48,9 +49,7 @@ describe DAV4Rack::Handler do
48
49
  end
49
50
 
50
51
  def url_escape(string)
51
- string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do
52
- '%' + $1.unpack('H2' * $1.size).join('%').upcase
53
- end.tr(' ', '+')
52
+ URI.escape(string)
54
53
  end
55
54
 
56
55
  def response_xml
@@ -136,8 +135,7 @@ describe DAV4Rack::Handler do
136
135
  end
137
136
 
138
137
  it 'should delete recursively' do
139
- mkcol('/folder')
140
- multi_status_created.should eq true
138
+ mkcol('/folder').should be_created
141
139
  put('/folder/a', :input => 'body').should be_created
142
140
  put('/folder/b', :input => 'body').should be_created
143
141
 
@@ -159,15 +157,13 @@ describe DAV4Rack::Handler do
159
157
 
160
158
  it 'should copy a single resource' do
161
159
  put('/test', :input => 'body').should be_created
162
- copy('/test', 'HTTP_DESTINATION' => '/copy')
163
- multi_status_no_content.should eq true
160
+ copy('/test', 'HTTP_DESTINATION' => '/copy').should be_created
164
161
  get('/copy').body.should == 'body'
165
162
  end
166
163
 
167
164
  it 'should copy a resource with escaped characters' do
168
165
  put(url_escape('/a b'), :input => 'body').should be_created
169
- copy(url_escape('/a b'), 'HTTP_DESTINATION' => url_escape('/a c'))
170
- multi_status_no_content.should eq true
166
+ copy(url_escape('/a b'), 'HTTP_DESTINATION' => url_escape('/a c')).should be_created
171
167
  get(url_escape('/a c')).should be_ok
172
168
  response.body.should == 'body'
173
169
  end
@@ -175,39 +171,32 @@ describe DAV4Rack::Handler do
175
171
  it 'should deny a copy without overwrite' do
176
172
  put('/test', :input => 'body').should be_created
177
173
  put('/copy', :input => 'copy').should be_created
178
- copy('/test', 'HTTP_DESTINATION' => '/copy', 'HTTP_OVERWRITE' => 'F')
179
-
180
- multistatus_response('/D:href').first.text.should =~ /http:\/\/localhost(:\d+)?\/test/
181
- multistatus_response('/D:status').first.text.should match(/412 Precondition Failed/)
182
-
174
+ copy('/test', 'HTTP_DESTINATION' => '/copy', 'HTTP_OVERWRITE' => 'F').should be_precondition_failed
183
175
  get('/copy').body.should == 'copy'
184
176
  end
185
177
 
186
178
  it 'should allow a copy with overwrite' do
187
179
  put('/test', :input => 'body').should be_created
188
180
  put('/copy', :input => 'copy').should be_created
189
- copy('/test', 'HTTP_DESTINATION' => '/copy', 'HTTP_OVERWRITE' => 'T')
190
- multi_status_no_content.should eq true
181
+ copy('/test', 'HTTP_DESTINATION' => '/copy', 'HTTP_OVERWRITE' => 'T').should be_no_content
191
182
  get('/copy').body.should == 'body'
192
183
  end
193
184
 
194
185
  it 'should copy a collection' do
195
- mkcol('/folder')
196
- multi_status_created.should eq true
186
+ mkcol('/folder').should be_created
197
187
  copy('/folder', 'HTTP_DESTINATION' => '/copy')
198
- multi_status_ok.should eq true
188
+ multi_status_created.should eq true
199
189
  propfind('/copy', :input => propfind_xml(:resourcetype))
200
190
  multistatus_response('/D:propstat/D:prop/D:resourcetype/D:collection').should_not be_empty
201
191
  end
202
192
 
203
193
  it 'should copy a collection resursively' do
204
- mkcol('/folder')
205
- multi_status_created.should eq true
194
+ mkcol('/folder').should be_created
206
195
  put('/folder/a', :input => 'A').should be_created
207
196
  put('/folder/b', :input => 'B').should be_created
208
197
 
209
198
  copy('/folder', 'HTTP_DESTINATION' => '/copy')
210
- multi_status_ok.should eq true
199
+ multi_status_created.should eq true
211
200
  propfind('/copy', :input => propfind_xml(:resourcetype))
212
201
  multistatus_response('/D:propstat/D:prop/D:resourcetype/D:collection').should_not be_empty
213
202
  get('/copy/a').body.should == 'A'
@@ -215,13 +204,12 @@ describe DAV4Rack::Handler do
215
204
  end
216
205
 
217
206
  it 'should move a collection recursively' do
218
- mkcol('/folder')
219
- multi_status_created.should eq true
207
+ mkcol('/folder').should be_created
220
208
  put('/folder/a', :input => 'A').should be_created
221
209
  put('/folder/b', :input => 'B').should be_created
222
210
 
223
211
  move('/folder', 'HTTP_DESTINATION' => '/move')
224
- multi_status_ok.should eq true
212
+ multi_status_created.should eq true
225
213
  propfind('/move', :input => propfind_xml(:resourcetype))
226
214
  multistatus_response('/D:propstat/D:prop/D:resourcetype/D:collection').should_not be_empty
227
215
 
@@ -232,15 +220,13 @@ describe DAV4Rack::Handler do
232
220
  end
233
221
 
234
222
  it 'should create a collection' do
235
- mkcol('/folder')
236
- multi_status_created.should eq true
223
+ mkcol('/folder').should be_created
237
224
  propfind('/folder', :input => propfind_xml(:resourcetype))
238
225
  multistatus_response('/D:propstat/D:prop/D:resourcetype/D:collection').should_not be_empty
239
226
  end
240
227
 
241
228
  it 'should return full urls after creating a collection' do
242
- mkcol('/folder')
243
- multi_status_created.should eq true
229
+ mkcol('/folder').should be_created
244
230
  propfind('/folder', :input => propfind_xml(:resourcetype))
245
231
  multistatus_response('/D:propstat/D:prop/D:resourcetype/D:collection').should_not be_empty
246
232
  multistatus_response('/D:href').first.text.should =~ /http:\/\/localhost(:\d+)?\/folder/
metadata CHANGED
@@ -1,80 +1,57 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: dav4rack
3
- version: !ruby/object:Gem::Version
4
- hash: 3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.11
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 2
9
- - 10
10
- version: 0.2.10
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Chris Roberts
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-12-22 00:00:00 -08:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2012-09-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: nokogiri
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &15276900 !ruby/object:Gem::Requirement
25
17
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 1
32
- - 4
33
- - 2
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
34
21
  version: 1.4.2
35
22
  type: :runtime
36
- version_requirements: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: uuidtools
39
23
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *15276900
25
+ - !ruby/object:Gem::Dependency
26
+ name: uuidtools
27
+ requirement: &15293080 !ruby/object:Gem::Requirement
41
28
  none: false
42
- requirements:
29
+ requirements:
43
30
  - - ~>
44
- - !ruby/object:Gem::Version
45
- hash: 9
46
- segments:
47
- - 2
48
- - 1
49
- - 1
31
+ - !ruby/object:Gem::Version
50
32
  version: 2.1.1
51
33
  type: :runtime
52
- version_requirements: *id002
53
- - !ruby/object:Gem::Dependency
54
- name: rack
55
34
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::Requirement
35
+ version_requirements: *15293080
36
+ - !ruby/object:Gem::Dependency
37
+ name: rack
38
+ requirement: &15292420 !ruby/object:Gem::Requirement
57
39
  none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- hash: 19
62
- segments:
63
- - 1
64
- - 1
65
- - 0
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
66
43
  version: 1.1.0
67
44
  type: :runtime
68
- version_requirements: *id003
45
+ prerelease: false
46
+ version_requirements: *15292420
69
47
  description: WebDAV handler for Rack
70
48
  email: chrisroberts.code@gmail.com
71
- executables:
49
+ executables:
72
50
  - dav4rack
73
51
  extensions: []
74
-
75
- extra_rdoc_files:
52
+ extra_rdoc_files:
76
53
  - README.rdoc
77
- files:
54
+ files:
78
55
  - .gitignore
79
56
  - LICENSE
80
57
  - dav4rack.gemspec
@@ -95,39 +72,29 @@ files:
95
72
  - bin/dav4rack
96
73
  - spec/handler_spec.rb
97
74
  - README.rdoc
98
- has_rdoc: true
99
75
  homepage: http://github.com/chrisroberts/dav4rack
100
76
  licenses: []
101
-
102
77
  post_install_message:
103
78
  rdoc_options: []
104
-
105
- require_paths:
79
+ require_paths:
106
80
  - lib
107
- required_ruby_version: !ruby/object:Gem::Requirement
81
+ required_ruby_version: !ruby/object:Gem::Requirement
108
82
  none: false
109
- requirements:
110
- - - ">="
111
- - !ruby/object:Gem::Version
112
- hash: 3
113
- segments:
114
- - 0
115
- version: "0"
116
- required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
88
  none: false
118
- requirements:
119
- - - ">="
120
- - !ruby/object:Gem::Version
121
- hash: 3
122
- segments:
123
- - 0
124
- version: "0"
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
125
93
  requirements: []
126
-
127
94
  rubyforge_project:
128
- rubygems_version: 1.4.2
95
+ rubygems_version: 1.8.17
129
96
  signing_key:
130
97
  specification_version: 3
131
98
  summary: WebDAV handler for Rack
132
99
  test_files: []
133
-
100
+ has_rdoc: true