Module: WebDAV

Defined in:
lib/davclient.rb

Overview

Main WebDAV client. Current working URL is stored in a tempfile named /tmp/cwurl.pid, where pid is the parent process. Username an password is stored in the ~/.netrc file. This means there is no need to set up any sessions or connections.

If a change directory command is executed with a relative path, like for instance WebDAV.cd(“../collection”), it will raise an exception if current working url has not been set. First a change directory command is executed it should use an absolute URL, like for instance WebDAV.cd(“www.webdav.org/collection/”).

If using an URL with a server name not found in the ~/.netrc file, instructions for adding the necessary servername, username and password will be printed to stdout.

Constant Summary collapse

VERSION =

:stopdoc:

'0.0.4'

Class Method Summary collapse

Class Method Details

.absoluteUrl(url) ⇒ Object

Make relative url absolute. Returns error if no current working url has been set.

Example:

WebDAV.cd("https://example.org/subfolder")
print WebDAV.absoluteUrl("..")  => "https://example.org/"


58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/davclient.rb', line 58

def self.absoluteUrl(url)
  if(not(url =~ /^http.?:\/\//))then
    cwurl = Pathname.new(self.CWURL)
    cwurl = cwurl + url
    url = cwurl.to_s
    # url = url + "/" if(not(url =~ /\/$/))

    if(not(url =~ /^http.?:\/\//))then
      raise "illegal url: " + url
    end
  end
  return url
end

.cd(url) ⇒ Object

Change current working url. Takes relative pathnames. First time this method is called, an absolute URL must be used. Raises exception if servername is not found in ~/.netrc file.

Examples:

WebDAV.cd("http://www.example.org")

WebDAV.cd("../folder")


98
99
100
101
102
103
104
105
106
107
# File 'lib/davclient.rb', line 98

def self.cd(url)
  url = absoluteUrl(url)
  url = url + "/" if(not(url =~ /\/$/))
  resource = WebDAV.propfind(url)
  if(resource and resource.isCollection?)then
    WebDAV.CWURL = url
  else
    raise Exception, "#{$0} cd: #{url}: No such collection on remote server."
  end
end

.cp(src, dest) ⇒ Object

Copy resources

Examples:

WebDAV.cp("src.html","https://example.org/destination/destination.html"


345
346
347
348
349
350
351
352
353
354
355
356
357
# File 'lib/davclient.rb', line 345

def self.cp(src,dest)
  srcUrl = absoluteUrl(src)
  destUrl = absoluteUrl(dest)

  # puts "DEBUG: " + srcUrl + " => " + destUrl
  curl_command = CURL_COPY.sub("<!--destination-->", destUrl) + " " + srcUrl
  response = DavClient.exec_curl(curl_command)

  if(response  == "")then
    return destUrl
  end
  return false
end

.CWURLObject

Returns current working url.



41
42
43
44
45
46
47
48
49
# File 'lib/davclient.rb', line 41

def self.CWURL
  return $CWURL if($CWURL)
  cwurl = nil
  filename = DavClient.cwurl_filename
  if(File.exists?(filename))
    File.open(filename, 'r') {|f| cwurl = f.read() }
  end
  return cwurl
end

.CWURL=(url) ⇒ Object

Sets current working url.

Current working url is stored in aa tempfile with parent process pid as part of the filename.



113
114
115
116
117
# File 'lib/davclient.rb', line 113

def self.CWURL=(url)
  $CWURL = url
  File.open(DavClient.cwurl_filename, 'w') {|f| f.write(url) }
  # puts "DEBUG: writing " + DavClient.cwurl_filename
end

.delete(url) ⇒ Object

Delete resource

Examples:

WebDAV.cd("https://example.org/folder")
WebDAV.mkcol("subfolder")
WebDAV.delete("subfolder")


387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/davclient.rb', line 387

def self.delete(url)

  url = absoluteUrl(url)

  curl_command = CURL_DELETE + url
  response = DavClient.exec_curl(curl_command)

  if(response  == "")then
    return url
  end
  if(not(response =~ /200 OK/)) then
    puts "Error:\nRequest:\n" + curl_command + "\n\nResponse: " + response
    return false
  end
  return url
end

.exists?(url) ⇒ Boolean

Returns true if resource exists

Returns:

  • (Boolean)


330
331
332
333
334
335
336
337
338
# File 'lib/davclient.rb', line 330

def self.exists?(url)
  url = absoluteUrl(url)
  props = WebDAV.propfind(url)
  if(props.to_s.size == 0)then
    return false
  else
    return true
  end
end

.find(*args, &block) ⇒ Object

Find files and folders.

Examples:

result = find( url [:type => "collection"|"resource"] [:recursive => true])

result = find( url, :type => "collection" ,:recursive => true)

You can also pass a block of code:

find( url, :type => "collection" ,:recursive => true) do |folder|
  puts folder.href
end

If no url is specified, current working url is used.

cd("https://webdav.org")
find() do |item|
  print item.title
end


211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'lib/davclient.rb', line 211

def self.find(*args, &block)

  if(args.size == 0)
    href = self.CWURL
  elsif(args.size == 1)
    if(args[0].class == String)
      href = args[0]
    else
      options = args[0]
    end
  elsif(args.size == 2)
    href = args[0]
    options = args[1]
  else
    raise "Illegal number of arguments."
  end

  if(href == nil )
    if(WebDAV.CWURL == nil)
      raise "no current working url set"
    else
      href = WebDAV.CWURL
    end
  end

  type = nil
  recursive = false
  if(options)then

    if(options[:type])then
      type = options[:type]
    end
    if(options[:recursive])then
      recursive = options[:recursive]
    end
  end
  begin
    dav_xml_output = propfind(href, :xml => true)
  rescue Exception => exception
    $stderr.puts "Warning: " + href + " : " + exception
    # raise "er
    return nil
  end
  if(not(dav_xml_output))then
    return nil
  end

  doc = Hpricot( dav_xml_output )
  items_filtered = Array.new()
  items = doc.search("//d:response").reverse

  # filter items
  items.each do |item|

    # Ignore info about root item (file or folder)
    if(item.href != href) then

      if(type == nil)then
        # No filters
        items_filtered.push(item)
        if(block) then
          yield item
        end

      else
        # Filter result set
        if((type == "collection" or type == "folder" or type == "directory") and item.isCollection? )then
          items_filtered.push(item)
          if(block) then
            yield item
          end
        end

        # TODO BUG: Item is not yielded if :type => "resource" is given...
        # puts "DEBUG: " + type + "  " + item.isCollection?.to_s
        if( (type == "file" or type == "resource") and item.isCollection? == false )then
          items_filtered.push(item)
          if(block) then
            yield item
          end
        end
      end

    end
  end

  if(recursive)then
    items_filtered.each do |item|
      if(item.collection && item.href != args[0])then
        result = find(item.href, args[1], &block)
        if(result != nil)
          items_filtered.concat( result)
        end
      end
    end
  end

  return items_filtered
end

.get(url) ⇒ Object

Get content of resource as string

Example:

html = WebDAV.get(url)

html = WebDAV.get("file_in_current_working_folder.html")


127
128
129
130
131
132
# File 'lib/davclient.rb', line 127

def self.get(url)
  url = absoluteUrl(url)

  curl_command = url
  return DavClient.exec_curl(curl_command)
end

.isCollection?(url) ⇒ Boolean

Boolean function that returns true if url is a collection

Example:

WebDAV.isCollection("../test.html") => false

Returns:

  • (Boolean)


77
78
79
80
81
82
83
84
85
86
# File 'lib/davclient.rb', line 77

def self.isCollection?(url)
  url = absoluteUrl(url)
  url = url + "/" if(not(url =~ /\/$/))
  resource = WebDAV.propfind(url)
  if(resource == nil)
    return false
  else
    return resource.isCollection?
  end
end

.mkcol(*args) ⇒ Object

Make collection Accepts relative url’s



313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/davclient.rb', line 313

def self.mkcol(*args) # url, props)
  url = args[0]
  props = args[3]
  url = absoluteUrl(url)
  curl_command = CURL_MKCOL + " " + url
  response = DavClient.exec_curl(curl_command)

  if(props)then
    proppatch(url,props)
  end
  if(response =~ />Created</)then
    return true
  end
  return response
end

.mv(src, dest) ⇒ Object

Move resources

Examples:

WebDAV.mv("src.html","https://example.org/destination/destination.html"


365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'lib/davclient.rb', line 365

def self.mv(src,dest)
  srcUrl = absoluteUrl(src)
  destUrl = absoluteUrl(dest)

  # puts "DEBUG: " + srcUrl + " => " + destUrl
  curl_command = CURL_MOVE.sub("<!--destination-->", destUrl) + " " + srcUrl
  response = DavClient.exec_curl(curl_command)

  if(response  == "")then
    return destUrl
  end
  return false
end

.options(url) ⇒ Object

Returns a string with the webservers WebDAV options (PUT, PROPFIND, etc.)



452
453
454
455
456
457
# File 'lib/davclient.rb', line 452

def self.options(url)
  if(not(url))
    url = self.CWURL
  end
  return DavClient.exec_curl(CURL_OPTIONS + url )
end

.propfind(*args) ⇒ Object

Get WebDAV properties

Examples:

item = propfind(url)                - Returns an Hpricot::Elem object

xml = propfind(url, :xml => true)   - Returns xml for debugging.


157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/davclient.rb', line 157

def self.propfind(*args)
  url = args[0]
  url = absoluteUrl(url)
  options = args[1]

  curl_command = CURL_PROPFIND + " \"" + url + "\""
  response = DavClient.exec_curl(curl_command)

  if(response == "")then
    return nil
  end

  if(not(response =~ /200 OK/)) then
    # puts "Error:\nRequest:\n" + curl_command + "\n\nResponse: " + response
    # exit(0)
    raise "Error:\nRequest:\n" + curl_command + "\n\nResponse: " + response
  end

  if(options and options[:xml])then
    return response
  end
  doc = Hpricot( response )
  items_filtered = Array.new()
  items = doc.search("//d:response").reverse
  items.each do |item|

    # Only return root item if folder
    if(item.href == url or item.href == url + "/" ) then
      return item
    end
  end
  return nil
end

.proppatch(url, property) ⇒ Object

Set WebDAV properties for url as xml.

Example:

WebDAV.proppatch("https://dav.webdav.org/folder","<contentLastModified>2007-12-12 12:00:00 GMT</contentLastModified>


139
140
141
142
143
144
145
146
147
148
# File 'lib/davclient.rb', line 139

def self.proppatch(url, property)
  url = absoluteUrl(url)
  curl_command = CURL_PROPPATCH + " \""+url+"\""
  curl_command = curl_command.gsub("<!--property-and-value-->",property)
  response = DavClient.exec_curl(curl_command)
  if(not(response =~ /200 OK/)) then
    puts "Error:\nRequest:\n" + curl_command + "\n\nResponse: " + response
    exit(0)
  end
end

.publish(url, string, props) ⇒ Object

Low level WebDAV publish

Example:

WebDAV.publish("https://dav.example.org/index.html","<h1>Hello</h1>",nil)


410
411
412
413
414
415
# File 'lib/davclient.rb', line 410

def self.publish(url, string, props)
  self.put_string(url, string)
  if(props)then
    self.proppatch(url,props)
  end
end

.put(url, file_name) ⇒ Object

Upload local file to webserver

Example:

WebDAV.put("https://example.org/myfile.html", "myfile.html")


441
442
443
444
445
446
447
448
449
# File 'lib/davclient.rb', line 441

def self.put(url, file_name)
  url = absoluteUrl(url)

  curl_command = CURL_UPLOAD + " " + file_name + " " + url
  response = DavClient.exec_curl(curl_command)
  if(response != "" and not(response =~ /200 OK/)) then
    raise "Error:\n WebDAV.put: WebDAV Request:\n" + curl_command + "\n\nResponse: " + response
  end
end

.put_string(url, str) ⇒ Object

Puts content of string to file on server with url

Example:

WebDAV.put("https://dav.webdav.org/file.html", "<html><h1>Test</h1></html>"


424
425
426
427
428
429
430
431
432
433
# File 'lib/davclient.rb', line 424

def self.put_string(url,str)
  url = absoluteUrl(url)

  if(url =~ /\/$/)then
    raise "Error: WebDAV.put_html: url can not be a collection (folder)."
  end

  filename = DavClient.string2tempfile(str)
  put(url,filename)
end

.versionObject

Returns the version string for the library.



36
37
38
# File 'lib/davclient.rb', line 36

def self.version
  VERSION
end