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"


334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/davclient.rb', line 334

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

  # puts "DEBUG: " + srcUrl + " => " + destUrl
  curl_command = CURL_COPY.sub("<!--destination-->", destUrl) + " " + srcUrl
  response = 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 = 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
# File 'lib/davclient.rb', line 113

def self.CWURL=(url)
  $CWURL = url
  File.open(cwurl_filename, 'w') {|f| f.write(url) }
end

.cwurl_filenameObject

Returns filename /tmp/cwurl.#pid that holds the current working directory for the shell’s pid



467
468
469
# File 'lib/davclient.rb', line 467

def self.cwurl_filename
  return tmp_folder +  "cwurl." + Process.ppid.to_s
end

.delete(url) ⇒ Object

Delete resource

Examples:

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


376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
# File 'lib/davclient.rb', line 376

def self.delete(url)

  url = absoluteUrl(url)

  curl_command = CURL_DELETE + url
  response = 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)


319
320
321
322
323
324
325
326
327
# File 'lib/davclient.rb', line 319

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 )

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


209
210
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
# File 'lib/davclient.rb', line 209

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
  dav_xml_output = propfind(href, :xml => true)
  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
        if(type == "file" and item.collection == 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")


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

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

  curl_command = "#{$curl} --netrc " + url
  return 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



302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/davclient.rb', line 302

def self.mkcol(*args) # url, props)
  url = args[0]
  props = args[3]
  url = absoluteUrl(url)
  curl_command = CURL_MKCOL + " " + url
  response = 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"


354
355
356
357
358
359
360
361
362
363
364
365
366
# File 'lib/davclient.rb', line 354

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

  # puts "DEBUG: " + srcUrl + " => " + destUrl
  curl_command = CURL_MOVE.sub("<!--destination-->", destUrl) + " " + srcUrl
  response = 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.)



437
438
439
440
441
442
# File 'lib/davclient.rb', line 437

def self.options(url)
  if(not(url))
    url = self.CWURL
  end
  return self.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.


156
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
# File 'lib/davclient.rb', line 156

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

  curl_command = CURL_PROPFIND + " \"" + url + "\""
  response = 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)
  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>


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

def self.proppatch(url, property)
  url = absoluteUrl(url)
  curl_command = CURL_PROPPATCH + " \""+url+"\""
  curl_command = curl_command.gsub("<!--property-and-value-->",property)
  response = 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)


399
400
401
402
403
404
# File 'lib/davclient.rb', line 399

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



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

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

  curl_command = "#{$curl} --netrc --silent --upload-file #{file_name} #{url}"
  response = 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>"


413
414
415
416
417
418
419
420
421
422
# File 'lib/davclient.rb', line 413

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 = string2tempfile(str)
  put(url,filename)
end

.string2tempfile(str) ⇒ Object

TODO: Move this to utility library Write string to tempfile and returns filename



455
456
457
458
459
460
461
# File 'lib/davclient.rb', line 455

def self.string2tempfile(str)
  tmp_dir = tmp_folder + rand.to_s[2..10] + "/"
  FileUtils.mkdir_p tmp_dir
  tmp_file = tmp_dir + "webdav.tmp"
  File.open(tmp_file, 'w') {|f| f.write(str) }
  return tmp_file
end

.tmp_folderObject

Returns name of temp folder we’re using TODO: Move this to utility library



446
447
448
449
450
# File 'lib/davclient.rb', line 446

def self.tmp_folder
  tmp_file = Tempfile.new("dummy").path
  basename = File.basename(tmp_file)
  return  tmp_file.gsub(basename, "")
end

.versionObject

Returns the version string for the library.



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

def self.version
  VERSION
end