fernyb_davclient 0.0.9
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.
- data/LICENSE +53 -0
- data/Manifest +38 -0
- data/README.rdoc +134 -0
- data/Rakefile +95 -0
- data/bin/dav +6 -0
- data/examples/clean_files.rb +131 -0
- data/examples/meta_tags_in_use.rb +64 -0
- data/examples/remove_ds_store.rb +15 -0
- data/examples/scrape_site.rb +36 -0
- data/examples/simple_find.rb +10 -0
- data/fernyb_davclient.gemspec +35 -0
- data/lib/davclient.rb +513 -0
- data/lib/davclient/curl_commands.rb +70 -0
- data/lib/davclient/dav-ls.rb +168 -0
- data/lib/davclient/dav-propfind.rb +92 -0
- data/lib/davclient/dav-put.rb +137 -0
- data/lib/davclient/davcli.rb +286 -0
- data/lib/davclient/hpricot_extensions.rb +149 -0
- data/lib/davclient/simple.rb +44 -0
- data/lib/davclient/termutil.rb +55 -0
- data/lib/davclient/util.rb +256 -0
- data/tests/dav.rb +12 -0
- data/tests/tc_dav-cat.rb +34 -0
- data/tests/tc_dav-cd.rb +45 -0
- data/tests/tc_dav-cp.rb +51 -0
- data/tests/tc_dav-delete.rb +37 -0
- data/tests/tc_dav-get.rb +63 -0
- data/tests/tc_dav-ls.rb +45 -0
- data/tests/tc_dav-mkcol.rb +64 -0
- data/tests/tc_dav-mv.rb +65 -0
- data/tests/tc_dav-propfind.rb +40 -0
- data/tests/tc_dav-put.rb +132 -0
- data/tests/tc_util.rb +39 -0
- data/tests/tc_webdav_basic.rb +86 -0
- data/tests/tc_webdav_publish.rb +63 -0
- data/tests/test_helper.rb +2 -0
- data/tests/ts_davclient.rb +12 -0
- data/todo +32 -0
- metadata +118 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
# require 'rubygems'
|
2
|
+
require 'termios'
|
3
|
+
|
4
|
+
# Prompt for password
|
5
|
+
# Extracted from Ian Macdonald's Ruby/Password gem.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# password = getc(message="Password: ", mask='*')
|
10
|
+
# puts "It's:" + password
|
11
|
+
|
12
|
+
class TermUtil
|
13
|
+
|
14
|
+
def self.echo(on=true, masked=false)
|
15
|
+
term = Termios::getattr( $stdin )
|
16
|
+
|
17
|
+
if on
|
18
|
+
term.c_lflag |= ( Termios::ECHO | Termios::ICANON )
|
19
|
+
else # off
|
20
|
+
term.c_lflag &= ~Termios::ECHO
|
21
|
+
term.c_lflag &= ~Termios::ICANON if masked
|
22
|
+
end
|
23
|
+
|
24
|
+
Termios::setattr( $stdin, Termios::TCSANOW, term )
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.getc(message="Password: ", mask='*')
|
28
|
+
# Save current buffering mode
|
29
|
+
buffering = $stdout.sync
|
30
|
+
|
31
|
+
# Turn off buffering
|
32
|
+
$stdout.sync = true
|
33
|
+
|
34
|
+
begin
|
35
|
+
echo(false, true)
|
36
|
+
print message if message
|
37
|
+
pw = ""
|
38
|
+
|
39
|
+
while ( char = $stdin.getc ) != 10 # break after [Enter]
|
40
|
+
putc mask
|
41
|
+
pw << char
|
42
|
+
end
|
43
|
+
|
44
|
+
ensure
|
45
|
+
echo true
|
46
|
+
print "\n"
|
47
|
+
end
|
48
|
+
|
49
|
+
# Restore original buffering mode
|
50
|
+
$stdout.sync = buffering
|
51
|
+
|
52
|
+
return pw
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'davclient/termutil'
|
3
|
+
require 'open3'
|
4
|
+
|
5
|
+
# DavClient Utilitis
|
6
|
+
|
7
|
+
module DavClient
|
8
|
+
|
9
|
+
# Loads contents of property file into an array
|
10
|
+
def self.load_davclientrc_file
|
11
|
+
properties_filename = ENV['HOME'] + "/.davclientrc"
|
12
|
+
return nil if not(File.exists?( properties_filename ))
|
13
|
+
|
14
|
+
properties = []
|
15
|
+
index = 0
|
16
|
+
File.open(properties_filename, 'r') do |properties_file|
|
17
|
+
properties_file.read.each_line do |line|
|
18
|
+
line.strip!
|
19
|
+
line = line.sub(/#.*/,"")
|
20
|
+
if (line[0] != ?# and line[0] != ?= )
|
21
|
+
i = line.index('=')
|
22
|
+
if (i)
|
23
|
+
# properties[line[0..i - 1].strip] = line[i + 1..-1].strip
|
24
|
+
key = line[0..i - 1].strip
|
25
|
+
if(key != "")
|
26
|
+
properties[index] = [ key, line[i + 1..-1].strip ]
|
27
|
+
index += 1
|
28
|
+
end
|
29
|
+
else
|
30
|
+
key = line
|
31
|
+
if(key != "" and not(key =~ /^\[/) )
|
32
|
+
properties[index] = [key, '']
|
33
|
+
index += 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
return properties
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# Returns options for an url read from .davclientrc file
|
45
|
+
def self.site_options(url, settings)
|
46
|
+
settings.each_index do | index|
|
47
|
+
key,value = settings[index]
|
48
|
+
# puts key + "--->" + value + " " + url
|
49
|
+
if(url.match(key) and key != "")then
|
50
|
+
return value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
return ""
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
# Returns filename /tmp/cwurl.#pid that holds the current working directory
|
59
|
+
# for the shell's pid
|
60
|
+
def self.cwurl_filename
|
61
|
+
return DavClient.tmp_folder + "cwurl." + Process.ppid.to_s
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Returns name of temp folder we're using
|
66
|
+
def self.tmp_folder
|
67
|
+
tmp_file = Tempfile.new("dummy").path
|
68
|
+
basename = File.basename(tmp_file)
|
69
|
+
return tmp_file.gsub(basename, "")
|
70
|
+
end
|
71
|
+
|
72
|
+
# Write string to tempfile and returns filename
|
73
|
+
def self.string2tempfile(str)
|
74
|
+
tmp_dir = DavClient.tmp_folder + rand.to_s[2..10] + "/"
|
75
|
+
FileUtils.mkdir_p tmp_dir
|
76
|
+
tmp_file = tmp_dir + "webdav.tmp"
|
77
|
+
File.open(tmp_file, 'w') {|f| f.write(str) }
|
78
|
+
return tmp_file
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
# Display instructions for adding credentials to .netrc file
|
83
|
+
def self.display_unauthorized_message(href)
|
84
|
+
puts "Error: 401 Unauthorized: " + href
|
85
|
+
href.match(/^http.*\/\/([^\/]*)/)
|
86
|
+
# puts "\nTry adding the following to your ~/.netrc file:"
|
87
|
+
# puts ""
|
88
|
+
# puts "machine #{$1}"
|
89
|
+
# puts " login " + ENV['USER']
|
90
|
+
# puts " password ********"
|
91
|
+
# puts ""
|
92
|
+
end
|
93
|
+
|
94
|
+
# Prompts user for username and password
|
95
|
+
# Prints hostname to console if set.
|
96
|
+
def self.prompt_for_username_and_password(host)
|
97
|
+
if(host)
|
98
|
+
print("Enter username for host '#{host}': ")
|
99
|
+
else
|
100
|
+
print("Username: ")
|
101
|
+
end
|
102
|
+
$stdout.flush
|
103
|
+
$username = STDIN.gets
|
104
|
+
$username.strip!
|
105
|
+
$password = TermUtil.getc(message="Password: ", mask='*')
|
106
|
+
$password.strip!
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# Spawns a new process. Gives curl password if password
|
111
|
+
# is not nil.
|
112
|
+
def self.spawn_curl(command, password)
|
113
|
+
PTY.spawn(command) do |reader, writer, pid|
|
114
|
+
if(password)
|
115
|
+
reader.expect(/^Enter.*:/)
|
116
|
+
writer.puts(password)
|
117
|
+
end
|
118
|
+
answer = reader.readlines.join("")
|
119
|
+
reader.close
|
120
|
+
return answer
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.exctract_host(url)
|
125
|
+
result = url.match(/http.*\/\/([^\/\?]*)/)
|
126
|
+
if(result)
|
127
|
+
return result[1]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
# Run 'curl' as a subprocess
|
133
|
+
def self.exec_curl(curl_command)
|
134
|
+
response = ""
|
135
|
+
|
136
|
+
puts curl_command if($DEBUG)
|
137
|
+
|
138
|
+
# Common options for all curl commands
|
139
|
+
options = "--netrc" # --user-agent
|
140
|
+
options << " --include" # => Include protocol headers in output
|
141
|
+
options << " --location" # => Follow Location: hints
|
142
|
+
curl_command = "#{$curl} " + options + " " + curl_command
|
143
|
+
Open3.popen3(curl_command) do |stdin, stdout, stderr|
|
144
|
+
|
145
|
+
response = stdout.readlines.join("")
|
146
|
+
|
147
|
+
if(response == "")
|
148
|
+
stderr = stderr.readlines.join("").sub(/^\W/,"")
|
149
|
+
if(stderr =~ /command/)
|
150
|
+
raise stderr
|
151
|
+
# puts "Error: " + stderr
|
152
|
+
# exit
|
153
|
+
end
|
154
|
+
if(stderr =~ /^curl:/)
|
155
|
+
raise stderr
|
156
|
+
# puts "Error: " + stderr
|
157
|
+
# puts
|
158
|
+
# puts curl_command
|
159
|
+
# puts
|
160
|
+
# exit
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
if(response =~ /401 Unauthorized/)then
|
166
|
+
href = curl_command.match( /"(http[^\"]*)"$/ )[0].gsub(/"/,"")
|
167
|
+
# self.display_unauthorized_message(href)
|
168
|
+
# exit
|
169
|
+
end
|
170
|
+
|
171
|
+
response_headers = response.split("\r\n\r\n")
|
172
|
+
response_body = response_headers.last
|
173
|
+
response_headers.pop
|
174
|
+
headers = response_headers.last
|
175
|
+
|
176
|
+
if response_headers.last.nil?
|
177
|
+
response_headers = response.split("\r\n\r\n")
|
178
|
+
headers = response_headers[0]
|
179
|
+
response_body = response_headers[1]
|
180
|
+
end
|
181
|
+
|
182
|
+
return {:head => headers, :body => response_body}
|
183
|
+
end
|
184
|
+
|
185
|
+
# Run 'curl' as a subprocess with pty
|
186
|
+
def self.exec_curl2(curl_command)
|
187
|
+
response = ""
|
188
|
+
puts curl_command if($DEBUG)
|
189
|
+
|
190
|
+
url = curl_command.match("http[^ ]*$").to_s
|
191
|
+
if(url == nil or url == "")then
|
192
|
+
puts "Curl command does not contain url."
|
193
|
+
raise RuntimeError
|
194
|
+
end
|
195
|
+
url = url.sub(/\"$/,"")
|
196
|
+
host = exctract_host(url)
|
197
|
+
|
198
|
+
settings = load_davclientrc_file
|
199
|
+
options = site_options(url, settings)
|
200
|
+
|
201
|
+
# puts;puts "url:" + url + " => '" + options + "'";
|
202
|
+
|
203
|
+
if(options =~ /password-prompt/) # no-password-prompt
|
204
|
+
options = options.sub(/password-prompt/, "")
|
205
|
+
|
206
|
+
if($username)
|
207
|
+
# Is username stored in $username variable ???
|
208
|
+
else
|
209
|
+
print("Username: ")
|
210
|
+
$stdout.flush
|
211
|
+
$username = STDIN.gets
|
212
|
+
$username.strip!
|
213
|
+
require 'davclient/termutil'
|
214
|
+
$password = TermUtil.getc(message="Password: ", mask='*')
|
215
|
+
# $password.strip!
|
216
|
+
puts "pass::" + $password
|
217
|
+
end
|
218
|
+
|
219
|
+
options += " --user " + $username + " "
|
220
|
+
|
221
|
+
end
|
222
|
+
|
223
|
+
curl_command = "#{$curl} " + options + " " + curl_command
|
224
|
+
|
225
|
+
puts
|
226
|
+
puts curl_command
|
227
|
+
|
228
|
+
Open3.popen3(curl_command) do |stdin, stdout, stderr|
|
229
|
+
stdin.puts $password # + "\n"
|
230
|
+
response = stdout.readlines.join("")
|
231
|
+
if(response == "")
|
232
|
+
stderr = stderr.readlines.join("").sub(/^\W/,"")
|
233
|
+
if(stderr =~ /command/)
|
234
|
+
# puts "Error: " + stderr
|
235
|
+
raise "Error: " + stderr
|
236
|
+
# exit
|
237
|
+
end
|
238
|
+
if(stderr =~ /^curl:/)
|
239
|
+
raise "Error: " + stderr
|
240
|
+
# puts "Error: " + stderr
|
241
|
+
# puts
|
242
|
+
# puts curl_command
|
243
|
+
# puts
|
244
|
+
# exit
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
if(response =~ /401 Unauthorized/)then
|
249
|
+
href = curl_command #.match( /"(http[^\"]*)"$/ )[0].gsub(/"/,"")
|
250
|
+
# DavClient.display_unauthorized_message(href)
|
251
|
+
raise "Could not execute :" + response
|
252
|
+
end
|
253
|
+
return response
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
data/tests/dav.rb
ADDED
data/tests/tc_dav-cat.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'test_helper'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'davclient'
|
5
|
+
require 'davclient'
|
6
|
+
require 'davclient/davcli'
|
7
|
+
require 'test/unit'
|
8
|
+
require 'test/zentest_assertions'
|
9
|
+
|
10
|
+
|
11
|
+
class TestDavCat < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def cat(*args)
|
14
|
+
out, err = util_capture do
|
15
|
+
DavCLI.cat(*args)
|
16
|
+
end
|
17
|
+
return [out.string, err.string]
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_basic_cat
|
21
|
+
url = "https://vortex-dav.uio.no/brukere/thomasfl/testfile.html"
|
22
|
+
content = WebDAV.get(url)
|
23
|
+
|
24
|
+
out, err = cat([url])
|
25
|
+
assert_equal content , out
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_relative_urls
|
29
|
+
WebDAV.cd("https://vortex-dav.uio.no/brukere/thomasfl/")
|
30
|
+
content = WebDAV.get("testfile.html")
|
31
|
+
assert content
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/tests/tc_dav-cd.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'rubygems'
|
3
|
+
require 'test/unit'
|
4
|
+
require 'test_helper'
|
5
|
+
require 'davclient'
|
6
|
+
require 'davclient/davcli'
|
7
|
+
require 'test/zentest_assertions'
|
8
|
+
|
9
|
+
class TestWDavCd < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def cd(*args)
|
12
|
+
out, err = util_capture do
|
13
|
+
DavCLI.cd(*args)
|
14
|
+
end
|
15
|
+
return ["", ""]
|
16
|
+
return [out.string, err.string]
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_basic_cd
|
20
|
+
url = "https://vortex-dav.uio.no/prosjekter/it-avisa/nyheter/2006/"
|
21
|
+
out, err = cd([url])
|
22
|
+
assert_equal url, WebDAV.CWURL
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_pathname
|
26
|
+
url = "https://vortex-dav.uio.no/prosjekter/it-avisa/nyheter/2006/"
|
27
|
+
out, err = cd([url])
|
28
|
+
assert_equal url, WebDAV.CWURL
|
29
|
+
out, err = cd([".."])
|
30
|
+
assert_equal url = "https://vortex-dav.uio.no/prosjekter/it-avisa/nyheter/", WebDAV.CWURL
|
31
|
+
|
32
|
+
out, err = WebDAV.cd("../../../brukere/thomasfl/")
|
33
|
+
assert_equal "https://vortex-dav.uio.no/brukere/thomasfl/", WebDAV.CWURL
|
34
|
+
|
35
|
+
exception = false
|
36
|
+
begin
|
37
|
+
out, err = WebDAV.cd(["../../../../../../"])
|
38
|
+
rescue Exception
|
39
|
+
exception = true
|
40
|
+
end
|
41
|
+
assert exception, "Should have raised an exception"
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/tests/tc_dav-cp.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'test_helper'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'davclient'
|
5
|
+
require 'davclient/davcli'
|
6
|
+
require 'test/unit'
|
7
|
+
require 'test/zentest_assertions'
|
8
|
+
|
9
|
+
class TestCP < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def cp(*args)
|
12
|
+
out, err = util_capture do
|
13
|
+
DavCLI.cp(*args)
|
14
|
+
end
|
15
|
+
return [out.string, err.string]
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_cp
|
19
|
+
$DEBUG = false
|
20
|
+
src = "https://vortex-dav.uio.no/brukere/thomasfl/testfile.html"
|
21
|
+
dest = "https://vortex-dav.uio.no/brukere/thomasfl/testfile_copy.html"
|
22
|
+
WebDAV.delete(dest)
|
23
|
+
assert !WebDAV.exists?(dest)
|
24
|
+
|
25
|
+
WebDAV.cp(src,dest)
|
26
|
+
assert WebDAV.exists?(dest)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_propfind_command_line
|
30
|
+
src = "https://vortex-dav.uio.no/brukere/thomasfl/testfile.html"
|
31
|
+
dest = "https://vortex-dav.uio.no/brukere/thomasfl/testfile_copy.html"
|
32
|
+
WebDAV.delete(dest)
|
33
|
+
assert !WebDAV.exists?(dest)
|
34
|
+
|
35
|
+
out, err = cp([src,dest])
|
36
|
+
assert WebDAV.exists?(dest)
|
37
|
+
|
38
|
+
# Relative url
|
39
|
+
WebDAV.delete(dest)
|
40
|
+
assert !WebDAV.exists?(dest)
|
41
|
+
|
42
|
+
|
43
|
+
WebDAV.cd("https://vortex-dav.uio.no/brukere/thomasfl/")
|
44
|
+
dest = "testfile_copy.html"
|
45
|
+
|
46
|
+
out, err = cp([src,dest])
|
47
|
+
assert WebDAV.exists?(dest)
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
end
|