webdavtools 0.0.1

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.
Files changed (8) hide show
  1. data/README.rdoc +57 -0
  2. data/bin/wdcd +43 -0
  3. data/bin/wdls +59 -0
  4. data/bin/wdprops +67 -0
  5. data/bin/wdput +3 -0
  6. data/bin/wdpwd +10 -0
  7. data/lib/webdavtools.rb +444 -0
  8. metadata +75 -0
data/README.rdoc ADDED
@@ -0,0 +1,57 @@
1
+ = WebDAVTools
2
+
3
+ * http://webdavtools.rubyforge.org
4
+ * http://rubyforge.org/mailman/listinfo/webdavtools-general
5
+
6
+ == DESCRIPTION:
7
+
8
+ WebDAVTools is a Ruby library for creating scripts to administrate content
9
+ and properties on servers that supports the WebDAV protocol. It can be used
10
+ to publish content to CMS systems like Plone and Content repositories like
11
+ Apache JackRabbit, that support the WebDAV protocol.
12
+
13
+ == Requirements
14
+
15
+ Unix and the command line utility curl installed.
16
+
17
+ == LIRBRARY SYNOPSIS:
18
+
19
+ require 'rubygems'
20
+ require 'webdavtools'
21
+
22
+ # Basic recursive tree walking
23
+ url = 'http://test.webdav.org/dav/'
24
+ WebDAV.find(url, :recursive => true) do |item|
25
+ puts item.href
26
+ end
27
+
28
+ == COMMAND LINE UTILITES:
29
+
30
+ WebDAVTools includes a small set of command line utilities, that should be familiar to unix users.
31
+ By using commands like wdcd to set current working url, wdls to list files and wdpwd to print
32
+ current working url, users can access files and folders on webdav servers. At the moment
33
+ only authentication by adding usernames and passwords to ~/.netrc file is supported.
34
+
35
+
36
+ == COMMAND LINE SYNOPSIS:
37
+
38
+ >wdcd http://test.webdav.org/dav/
39
+ http://test.webdav.org/dav/
40
+ >wdls
41
+ images/
42
+ index.html
43
+ >wdpwd
44
+ http://test.webdav.org/dav/
45
+
46
+ == INSTALL:
47
+
48
+ [sudo] gem sources -a http://gems.github.com
49
+ [sudo] gem install webdavtools
50
+
51
+ or
52
+
53
+ git clone git://github.com/thomasfl/webdavtools.git
54
+ cd webdavtools
55
+ rake install
56
+
57
+
data/bin/wdcd ADDED
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'webdavtools'
4
+
5
+ url = ARGV[0]
6
+ if(url =~ /^http/)then
7
+ resource = WebDAV.propfind(url)
8
+ if(resource and resource.isCollection?)then
9
+ WebDAV.CWURL = url
10
+ puts "Set WebDAV URL: " + url
11
+ else
12
+ puts "Error: URL is not a WebDAV collection."
13
+ end
14
+ elsif(url)then
15
+ cwurl = WebDAV.CWURL
16
+ if(not cwurl =~ /\/$/)then
17
+ cwurl += "/"
18
+ end
19
+
20
+ item = WebDAV.propfind(cwurl)
21
+ require 'pp'
22
+ # pp item
23
+ type = item.collection?
24
+ puts "DEBUG: type:" + type.to_s
25
+ end
26
+
27
+
28
+ exit
29
+
30
+ if(not url)then
31
+ url = WebDAV.CWURL
32
+ if(not url)then
33
+ puts "wdls: no current working url"
34
+ puts "Usage: Use 'wdopen url' or 'wdcd [url|dir] to set current working url "
35
+ exit
36
+ end
37
+ end
38
+
39
+ WebDAV.find(url, :recursive => false ) do |item|
40
+ puts item.href
41
+ end
42
+
43
+ # TODO only works on collections, should give som info about resources too.
data/bin/wdls ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'webdavtools'
4
+ require 'optparse'
5
+
6
+ options = {}
7
+
8
+ optparse = OptionParser.new do|opts|
9
+ opts.banner = "Usage: #{$0} [options] url"
10
+
11
+ opts.on( '-h', '--help', 'Display this screen' ) do
12
+ puts opts
13
+ exit
14
+ end
15
+
16
+ options[:longFormat] = false
17
+ opts.on( '-l', "List in long format" ) do
18
+ options[:longFormat] = true
19
+ end
20
+
21
+ options[:showUrl] = false
22
+ opts.on('-a', "Include full url in names.") do
23
+ options[:showUrl] = true
24
+ end
25
+
26
+ end
27
+
28
+ begin
29
+ optparse.parse!
30
+ rescue
31
+ puts "Error: " + $!
32
+ puts optparse
33
+ exit
34
+ end
35
+
36
+
37
+ url = ARGV[0]
38
+ if(not url)then
39
+ url = WebDAV.CWURL
40
+ if(not url)then
41
+ puts "wdls: no current working url"
42
+ puts "Usage: Use 'wdopen url' or 'wdcd [url|dir] to set current working url "
43
+ exit
44
+ end
45
+ end
46
+
47
+ WebDAV.find(url, :recursive => false ) do |item|
48
+ if(options[:showUrl])then
49
+ puts item.href
50
+ elsif(options[:longFormat])
51
+
52
+ else
53
+ print item.basename
54
+ print "/" if item.isCollection?
55
+ puts
56
+ end
57
+ end
58
+
59
+ # TODO only works on collections, should give som info about resources too.
data/bin/wdprops ADDED
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'webdavtools'
4
+ require 'optparse'
5
+
6
+ options = {}
7
+
8
+ title = nil
9
+ optparse = OptionParser.new do|opts|
10
+ opts.banner = "Usage: #{$0} [options] url"
11
+
12
+ opts.on( '-h', '--help', 'Display this screen' ) do
13
+ puts opts
14
+ exit
15
+ end
16
+
17
+ options[:xml] = false
18
+ opts.on( '-x', '--xml', "Return full xml" ) do
19
+ options[:xml] = true
20
+ end
21
+
22
+ options[:children] = false
23
+ opts.on('-c', '--children', "Show children if viewing collection (folder)") do
24
+ options[:children] = true
25
+ end
26
+
27
+ end
28
+
29
+ begin
30
+ optparse.parse!
31
+ rescue
32
+ puts "Error: " + $!
33
+ puts optparse
34
+ exit
35
+ end
36
+
37
+ url = ARGV[0]
38
+ if(not(url)) then
39
+ puts "Error: Missing mandatory url"
40
+ puts optparse
41
+ exit
42
+ end
43
+
44
+ if(options[:xml])then
45
+ puts WebDAV.propfind(url, :xml => true)
46
+ exit
47
+ end
48
+
49
+ item = WebDAV.propfind(url)
50
+ puts item.collection
51
+
52
+ prev_url = nil
53
+ WebDAV.find(url, :children => options[:children]) do | url, item |
54
+ if(prev_url != url) then
55
+ puts
56
+ puts "url = " + url
57
+ prev_url = url
58
+ end
59
+
60
+ name = item.prefix
61
+ if(item.namespace)then
62
+ name = name + "(" + item.namespace + ")"
63
+ end
64
+ name = name + item.name
65
+ puts name.ljust(40) + " = '" + item.text.to_s + "'"
66
+
67
+ end
data/bin/wdput ADDED
@@ -0,0 +1,3 @@
1
+ #!/bin/env ruby
2
+ require 'webdavtools'
3
+
data/bin/wdpwd ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'webdavtools'
4
+
5
+ url = WebDAV.CWURL
6
+ if(url)then
7
+ puts url
8
+ else
9
+ puts "wdpwd: no current working url set. Use 'wdcd url' to set url."
10
+ end
@@ -0,0 +1,444 @@
1
+ # -*- coding: utf-8 -*-
2
+ # File: webdavtools.rb - WebDAV library
3
+
4
+ require 'rubygems'
5
+ require 'hpricot'
6
+
7
+ # :stopdoc:
8
+
9
+ # Path to curl executable:
10
+ $curl = "/usr/local/bin/curl"
11
+
12
+ # Templates for curl commands:
13
+ curl_propfind_cmd = <<EOF
14
+ #{$curl}
15
+ --request PROPFIND
16
+ --header 'Content-Type: text/xml; charset="utf-8"'
17
+ --header "Depth: 1"
18
+ --data-ascii '<?xml version="1.0" encoding="utf-8"?>
19
+ <DAV:propfind xmlns:DAV="DAV:"><DAV:allprop/></DAV:propfind>'
20
+ --netrc
21
+ --silent
22
+ EOF
23
+ CURL_PROPFIND = curl_propfind_cmd.gsub("\n","").gsub(/ +/," ")
24
+
25
+ curl_proppatch_cmd = <<EOF
26
+ #{$curl}
27
+ --request PROPPATCH
28
+ --header 'Content-Type: text/xml; charset="utf-8"'
29
+ --header "Depth: 1"
30
+ --data-ascii '<?xml version="1.0"?>
31
+ <d:propertyupdate xmlns:d="DAV:" xmlns:v="vrtx">
32
+ <d:set>
33
+ <d:prop>
34
+ <!--property-and-value-->
35
+ </d:prop>
36
+ </d:set>
37
+ </d:propertyupdate>'
38
+ --netrc
39
+ --silent
40
+ EOF
41
+ CURL_PROPPATCH = curl_proppatch_cmd.gsub("\n","").gsub(/ +/," ")
42
+
43
+ curl_delete_cmd = <<EOF
44
+ #{$curl}
45
+ --request DELETE
46
+ --header 'Content-Type: text/xml; charset="utf-8"'
47
+ --netrc
48
+ --silent
49
+ EOF
50
+ CURL_DELETE = curl_delete_cmd.gsub("\n","").gsub(/ +/," ") + " "
51
+
52
+ curl_mkcol_cmd = <<EOF
53
+ #{$curl}
54
+ --request MKCOL
55
+ --header 'Content-Type: text/xml; charset="utf-8"'
56
+ --netrc
57
+ --silent
58
+ EOF
59
+ CURL_MKCOL = curl_mkcol_cmd.gsub("\n","").gsub(/ +/," ") + " "
60
+
61
+ # Disse er ikke i bruk lenger.
62
+ # Lag eventuelt et bibliotek som holder orden
63
+ # på vortex typer ut fra http://vortex-dev.uio.no/vrtx/resourcetypes.txt
64
+ EVENT_FOLDER = '<v:collection-type xmlns:v="vrtx">event-listing</v:collection-type>' +
65
+ '<v:resourceType xmlns:v="vrtx">event-listing</v:resourceType>'
66
+ ARTICLE_FOLDER = '<v:collection-type xmlns:v="vrtx">article-listing</v:collection-type>' +
67
+ '<v:resourceType xmlns:v="vrtx">article-listing</v:resourceType>'
68
+
69
+ # :startdoc:
70
+
71
+ # WebDAV utility functions
72
+ module WebDAV
73
+
74
+ # Returns current working url. Used by command line utilites
75
+ def self.CWURL
76
+ cwurl = ""
77
+ File.open("/tmp/cwurl", 'r') {|f| cwurl = f.read() }
78
+ return cwurl
79
+ end
80
+
81
+ # Sets current working url
82
+ def self.CWURL=(url)
83
+ File.open("/tmp/cwurl", 'w') {|f| f.write(url) }
84
+ end
85
+
86
+ # :stopdoc:
87
+ VERSION = '0.1.0'
88
+ # :startdoc:
89
+
90
+ # Returns the version string for the library.
91
+ #
92
+ def self.version
93
+ VERSION
94
+ end
95
+
96
+ # Get content as string
97
+ # Example:
98
+ # html = WebDAV.get(url)
99
+ def self.get(href)
100
+ curlCommand = "#{$curl} --netrc --silent " + href
101
+ curl_output = IO.popen(curlCommand).readlines().join("")
102
+ return curl_output
103
+ end
104
+
105
+ # Set WebDAV properties for url as xml.
106
+ def self.proppatch(href, property)
107
+ curlCommand = CURL_PROPPATCH + " \""+href+"\""
108
+ curlCommand = curlCommand.gsub("<!--property-and-value-->",property)
109
+ response = IO.popen(curlCommand).readlines().join("")
110
+ if(not(response =~ /200 OK/)) then
111
+ puts "Error:\nRequest:\n" + curlCommand + "\n\nResponse: " + response
112
+ exit(0)
113
+ end
114
+ end
115
+
116
+ # Get WebDAV properties
117
+ # Examples:
118
+ # item = propfind(url) - Returns a Hpricot::Elem object
119
+ # xml = propfind(url, :xml => true) - Returns xml for debugging.
120
+ def self.propfind(*args)
121
+ href = args[0]
122
+ options = args[1]
123
+
124
+ curlCommand = CURL_PROPFIND + " \"" + href + "\""
125
+ dav_xml_output = IO.popen(curlCommand).readlines().join("")
126
+ if(dav_xml_output =~ /401 Unauthorized/)then
127
+ self.display_unauthorized_message(href)
128
+ exit
129
+ end
130
+ if(dav_xml_output == "")then
131
+ # No response
132
+ return nil
133
+ end
134
+ if(not(dav_xml_output =~ /200 OK/)) then
135
+ puts "Error:\nRequest:\n" + curlCommand + "\n\nResponse: " + dav_xml_output
136
+ exit(0)
137
+ end
138
+
139
+ if(options and options[:xml])then
140
+ return dav_xml_output
141
+ end
142
+ doc = Hpricot( dav_xml_output )
143
+ items_filtered = Array.new()
144
+ items = doc.search("//d:response").reverse
145
+ items.each do |item|
146
+
147
+ # Only return root item if folder
148
+ if(item.href == href) then
149
+ return item
150
+ end
151
+ end
152
+ return nil
153
+ end
154
+
155
+ # Find files and folders:
156
+ # Examples:
157
+ #
158
+ # find( url )
159
+ # find( url, :type => "collection" ,:recursive => true)
160
+ # find( url, :type => "collection" ,:recursive => true) do |folder|
161
+ # puts folder.href
162
+ # end
163
+ #
164
+ def self.find(*args, &block)
165
+ href = args[0]
166
+ options = args[1]
167
+ type = nil
168
+ recursive = false
169
+ if(options)then
170
+
171
+ if(options[:type])then
172
+ type = options[:type]
173
+ end
174
+ if(options[:recursive])then
175
+ recursive = options[:recursive]
176
+ end
177
+ end
178
+ dav_xml_output = propfind(href, :xml => true)
179
+ if(not(dav_xml_output))then
180
+ return nil
181
+ end
182
+
183
+ doc = Hpricot( dav_xml_output )
184
+ # puts dav_xml_output;exit(0)
185
+ items_filtered = Array.new()
186
+ items = doc.search("//d:response").reverse
187
+
188
+ # filter items
189
+ items.each do |item|
190
+
191
+ # Ignore info about root item (file or folder)
192
+ if(item.href != href) then
193
+
194
+ if(type == nil)then
195
+ # No filters
196
+ items_filtered.push(item)
197
+ if(block) then
198
+ yield item
199
+ end
200
+
201
+ else
202
+ # Filter result set
203
+ if((type == "collection" or type == "folder") and item.collection )then
204
+ items_filtered.push(item)
205
+ if(block) then
206
+ yield item
207
+ end
208
+ end
209
+ if(type == "file" and item.collection == false )then
210
+ items_filtered.push(item)
211
+ if(block) then
212
+ yield item
213
+ end
214
+ end
215
+ end
216
+
217
+ end
218
+ end
219
+
220
+ if(recursive)then
221
+ items_filtered.each do |item|
222
+ if(item.collection && item.href != args[0])then
223
+ items_filtered.concat(find(item.href, args[1], &block))
224
+ end
225
+ end
226
+ end
227
+
228
+ return items_filtered
229
+ end
230
+
231
+ # Make collection
232
+ def self.mkcol(href,props)
233
+ cmd = CURL_MKCOL + " " + href
234
+ result = execute_curl_cmd(cmd)
235
+ if(props)then
236
+ proppatch(href,props)
237
+ end
238
+ if(result =~ />Created</)then
239
+ return true
240
+ end
241
+ return result
242
+ end
243
+
244
+ def self.delete(href)
245
+ curl_delete_command = CURL_DELETE + href
246
+
247
+ response = IO.popen(curl_delete_command).readlines().join("")
248
+ if(response =~ /401 Unauthorized/) then
249
+ display_unauthorized_message(href)
250
+ exit
251
+ end
252
+ if(response == "")then
253
+ return false
254
+ end
255
+ if(not(response =~ /200 OK/)) then
256
+ puts "Error:\nRequest:\n" + curl_delete_command + "\n\nResponse: " + response
257
+ return false
258
+ end
259
+ return true
260
+ end
261
+
262
+
263
+ # Low level WebDAV publish
264
+ # Example:
265
+ # WebDAV.publish("https://dav.example.org/index.html","<h1>Hello</h1>",nil)
266
+ def self.publish(url, string, props)
267
+ self.put_string(url, string)
268
+ if(props)then
269
+ self.proppatch(url,props)
270
+ end
271
+ end
272
+
273
+
274
+ # PUT content
275
+ # Example:
276
+ # WebDAV.put("https://dav.webdav.org/file.html", "<html><h1>Test</h1></html>"
277
+ def self.put_string(url, html)
278
+ if(url =~ /\/$/)then
279
+ raise "Error: WebDAV.put_html: url can not be a collection (folder)."
280
+ end
281
+
282
+ tmp_dir = "/tmp/" + rand.to_s[2..10] + "/"
283
+ FileUtils.mkdir_p tmp_dir
284
+ tmp_file = tmp_dir + "webdav.tmp"
285
+ File.open(tmp_file, 'w') {|f| f.write(html) }
286
+
287
+ curl_put_cmd = "#{$curl} --netrc --silent --upload-file #{tmp_file} #{url}"
288
+ response = IO.popen(curl_put_cmd).readlines().join("")
289
+ if(response != "" and not(response =~ /200 OK/)) then
290
+ raise "Error:\n WebDAV.put: WebDAV Request:\n" + CURL_PUT + "\n\nResponse: " + response
291
+ end
292
+ end
293
+
294
+ # TODO put file utility
295
+ # TESTME
296
+ def put_file(filename, href)
297
+ # TODO Detect if href is a collection or not??
298
+ curl_put_cmd = "#{$curl} --netrc --silent --request PUT #{filename} #{href}"
299
+ return execute_curl_cmd(curl_put_cmd)
300
+ end
301
+
302
+ # TODO ????
303
+ def put_html_file(url_folder, filename, html)
304
+ # Write html
305
+ end
306
+
307
+
308
+ private
309
+
310
+ def self.display_unauthorized_message(href)
311
+ puts "Error: 401 Unauthorized: " + href
312
+ href.match(/^http.*\/\/([^\/]*)/)
313
+ puts "\nTry adding the following to your ~/.netrc file:"
314
+ puts ""
315
+ puts "machine #{$1}"
316
+ puts " login " + ENV['USER']
317
+ puts " password ********"
318
+ puts ""
319
+ end
320
+
321
+ def self.execute_curl_cmd(cmd)
322
+ response = IO.popen(cmd).readlines().join("")
323
+ if(response =~ /401 Unauthorized/) then
324
+ display_unauthorized_message(href)
325
+ exit
326
+ end
327
+ if(response == "")then
328
+ return false
329
+ end
330
+ return response
331
+ end
332
+
333
+ end
334
+
335
+ # TODO Extract to ruby sourcefile
336
+
337
+ # Add custom functionality to the xml parser (monkey patching):
338
+ module Hpricot
339
+
340
+
341
+ # TODO: url method as alias for href
342
+
343
+ class Elem
344
+
345
+ def method_missing(method_name, *args)
346
+ if(args.size == 0) then
347
+ return property(method_name.to_s)
348
+ end
349
+ raise "Method missing"
350
+ end
351
+
352
+ def href()
353
+ self.at("d:href").innerText
354
+ end
355
+
356
+ def isCollection?()
357
+ self.at("d:collection") != nil
358
+ end
359
+
360
+ end
361
+
362
+ # TODO Not used. Delete???
363
+ def type_convert_value(value)
364
+ if(returnValue == "true")then
365
+ return true
366
+ end
367
+ if(returnValue == "false")then
368
+ return false
369
+ end
370
+ # Number format???
371
+ ## Dato format
372
+ return returnValue
373
+ end
374
+
375
+ # TODO: Make list of recognized namespace prefixes configurable
376
+ # Get property.
377
+ # Example:
378
+ # page = WebDAV.find(url)
379
+ # print page.property("published-date")
380
+ def property(name)
381
+
382
+ property = property = self.at(name)
383
+ if(property)then
384
+ returnValue = property.innerText
385
+ return returnValue
386
+ end
387
+
388
+ property = property = self.at(name.downcase)
389
+ if(property)then
390
+ return property.innerText
391
+ end
392
+
393
+ vrtx_property = self.at("v:" + name)
394
+ if(vrtx_property)then
395
+ return vrtx_property.innerText
396
+ end
397
+
398
+ vrtx_property = self.at("v:" + name.downcase)
399
+ if(vrtx_property)then
400
+ return vrtx_property.innerText
401
+ end
402
+
403
+ dav_property = self.at("d:" +name)
404
+ if( dav_property)then
405
+ return dav_property.innerText
406
+ end
407
+
408
+ dav_property = self.at("d:" +name.downcase)
409
+ if( dav_property)then
410
+ return dav_property.innerText
411
+ end
412
+
413
+ return nil
414
+ end
415
+
416
+ def basename
417
+ File.basename(self.at("d:href").innerText)
418
+ end
419
+
420
+ # TODO: Move to vortex_lib.rb
421
+ def dateProperty(name)
422
+ date = self.property(name)
423
+ if(date =~ /\dZ$/)then
424
+ # Fix for bug in vortex:
425
+ #
426
+ # Some date properties are in xmlshcema datetime format, but
427
+ # all tough the time seems to be localtime the timezone is
428
+ # specified as Z not CEST. Fix is to set timezone and add
429
+ # 2 hours.
430
+ date = date.gsub(/\dZ$/," CEST")
431
+ time = Time.parse(date)
432
+ time = time + (60 * 60 * 2)
433
+ return time
434
+ end
435
+ time = Time.parse(date)
436
+ return time
437
+ end
438
+
439
+ # Set the items WebDAV properties. Properties must be a string with XML.
440
+ def proppatch(properties)
441
+ WebDAV.proppatch(href, properties)
442
+ end
443
+
444
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: webdavtools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Thomas Flemming
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-05 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hpricot
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0.6"
24
+ version:
25
+ description: "WebDAVTools is a Ruby Library and a set of command line utilities for accessing files and folders on WebDAV servers. "
26
+ email: thomas.flemming@gmail.com
27
+ executables:
28
+ - wdcd
29
+ - wdls
30
+ - wdprops
31
+ - wdput
32
+ - wdpwd
33
+ extensions: []
34
+
35
+ extra_rdoc_files:
36
+ - README.rdoc
37
+ files:
38
+ - lib/webdavtools.rb
39
+ - bin/wdcd
40
+ - bin/wdls
41
+ - bin/wdprops
42
+ - bin/wdput
43
+ - bin/wdpwd
44
+ - README.rdoc
45
+ has_rdoc: true
46
+ homepage: http://folk.uio.no/thomasfl
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options: []
51
+
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements:
67
+ - cURL command line tool available from http://curl.haxx.se/
68
+ - Servername, username and password must be supplied in ~/.netrc file.
69
+ rubyforge_project: webdavtools
70
+ rubygems_version: 1.3.5
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: Command line WebDAV client and Ruby library.
74
+ test_files: []
75
+