webdavtools 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+