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