net_dav 0.2.2 → 0.3.0
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/Rakefile +5 -1
- data/VERSION +1 -1
- data/bin/dav +4 -2
- data/lib/net/dav.rb +82 -21
- data/net_dav.gemspec +2 -2
- metadata +2 -2
data/Rakefile
CHANGED
|
@@ -36,7 +36,11 @@ task :spec => :check_dependencies
|
|
|
36
36
|
|
|
37
37
|
task :default => :spec
|
|
38
38
|
|
|
39
|
-
task
|
|
39
|
+
task "dist" => [:clean, :release]
|
|
40
|
+
|
|
41
|
+
task "dist:patch" => [:clean, "version:bump:patch", :release]
|
|
42
|
+
|
|
43
|
+
task "dist:minor" => [:clean, "version:bump:minor", :release]
|
|
40
44
|
|
|
41
45
|
task :clean do
|
|
42
46
|
Dir.glob("**/*~").each do |file|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.3.0
|
data/bin/dav
CHANGED
|
@@ -6,6 +6,9 @@ require 'net/dav'
|
|
|
6
6
|
|
|
7
7
|
dav_user = ENV['DAVUSER']
|
|
8
8
|
dav_pass = ENV['DAVPASS']
|
|
9
|
+
disable_basic_auth = (ENV['DISABLE_BASIC_AUTH'] && ENV['DISABLE_BASIC_AUTH'] != "0")
|
|
10
|
+
enable_curl = !(ENV['DISABLE_CURL'] && ENV['DISABLE_CURL'] != "0")
|
|
11
|
+
|
|
9
12
|
cmd = $*[0]
|
|
10
13
|
|
|
11
14
|
def print_usage
|
|
@@ -36,9 +39,8 @@ else
|
|
|
36
39
|
url = URI.parse $*[1]
|
|
37
40
|
end
|
|
38
41
|
|
|
39
|
-
enable_curl = !(ENV['DISABLE_CURL'] && ENV['DISABLE_CURL'] != "0")
|
|
40
|
-
|
|
41
42
|
dav = Net::DAV.new(url, :curl => enable_curl)
|
|
43
|
+
dav.disable_basic_auth = disable_basic_auth
|
|
42
44
|
|
|
43
45
|
if (url.scheme == 'https')
|
|
44
46
|
dav.verify_callback = lambda do |preverify_ok, x509_store|
|
data/lib/net/dav.rb
CHANGED
|
@@ -3,6 +3,7 @@ require 'uri'
|
|
|
3
3
|
require 'nokogiri'
|
|
4
4
|
require 'net/dav/item'
|
|
5
5
|
require 'base64'
|
|
6
|
+
require 'digest/md5'
|
|
6
7
|
begin
|
|
7
8
|
require 'curb'
|
|
8
9
|
rescue LoadError
|
|
@@ -15,6 +16,8 @@ module Net #:nodoc:
|
|
|
15
16
|
class NetHttpHandler
|
|
16
17
|
attr_writer :user, :pass
|
|
17
18
|
|
|
19
|
+
attr_accessor :disable_basic_auth
|
|
20
|
+
|
|
18
21
|
def verify_callback=(callback)
|
|
19
22
|
@http.verify_callback = callback
|
|
20
23
|
end
|
|
@@ -24,6 +27,7 @@ module Net #:nodoc:
|
|
|
24
27
|
end
|
|
25
28
|
|
|
26
29
|
def initialize(uri)
|
|
30
|
+
@disable_basic_auth = false
|
|
27
31
|
@uri = uri
|
|
28
32
|
case @uri.scheme
|
|
29
33
|
when "http"
|
|
@@ -69,9 +73,6 @@ module Net #:nodoc:
|
|
|
69
73
|
req.content_length = length
|
|
70
74
|
headers.each_pair { |key, value| req[key] = value } if headers
|
|
71
75
|
req.content_type = 'text/xml; charset="utf-8"'
|
|
72
|
-
if (@user)
|
|
73
|
-
req.basic_auth @user, @pass
|
|
74
|
-
end
|
|
75
76
|
res = handle_request(req, headers)
|
|
76
77
|
res
|
|
77
78
|
end
|
|
@@ -87,9 +88,6 @@ module Net #:nodoc:
|
|
|
87
88
|
req.body = body
|
|
88
89
|
headers.each_pair { |key, value| req[key] = value } if headers
|
|
89
90
|
req.content_type = 'text/xml; charset="utf-8"'
|
|
90
|
-
if (@user)
|
|
91
|
-
req.basic_auth @user, @pass
|
|
92
|
-
end
|
|
93
91
|
res = handle_request(req, headers)
|
|
94
92
|
res
|
|
95
93
|
end
|
|
@@ -103,9 +101,6 @@ module Net #:nodoc:
|
|
|
103
101
|
raise "unkown returning_body verb #{verb}"
|
|
104
102
|
end
|
|
105
103
|
headers.each_pair { |key, value| req[key] = value } if headers
|
|
106
|
-
if (@user)
|
|
107
|
-
req.basic_auth @user, @pass
|
|
108
|
-
end
|
|
109
104
|
res = handle_request(req, headers, MAX_REDIRECTS, &block)
|
|
110
105
|
res.body
|
|
111
106
|
end
|
|
@@ -123,9 +118,6 @@ module Net #:nodoc:
|
|
|
123
118
|
req.body = body
|
|
124
119
|
headers.each_pair { |key, value| req[key] = value } if headers
|
|
125
120
|
req.content_type = 'text/xml; charset="utf-8"'
|
|
126
|
-
if (@user)
|
|
127
|
-
req.basic_auth @user, @pass
|
|
128
|
-
end
|
|
129
121
|
res = handle_request(req, headers)
|
|
130
122
|
res
|
|
131
123
|
end
|
|
@@ -144,7 +136,21 @@ module Net #:nodoc:
|
|
|
144
136
|
response = @http.request(req)
|
|
145
137
|
end
|
|
146
138
|
case response
|
|
147
|
-
when Net::HTTPSuccess then
|
|
139
|
+
when Net::HTTPSuccess then
|
|
140
|
+
return response
|
|
141
|
+
when Net::HTTPUnauthorized then
|
|
142
|
+
response.error! unless @user
|
|
143
|
+
response.error! if req['authorization']
|
|
144
|
+
new_req = clone_req(req.path, req, headers)
|
|
145
|
+
if response['www-authenticate'] =~ /^Basic/
|
|
146
|
+
if disable_basic_auth
|
|
147
|
+
raise "server requested basic auth, but that is disabled"
|
|
148
|
+
end
|
|
149
|
+
new_req.basic_auth @user, @pass
|
|
150
|
+
else
|
|
151
|
+
digest_auth(new_req, @user, @pass, response)
|
|
152
|
+
end
|
|
153
|
+
return handle_request(new_req, headers, limit - 1, &block)
|
|
148
154
|
when Net::HTTPRedirection then
|
|
149
155
|
location = URI.parse(response['location'])
|
|
150
156
|
if (@uri.scheme != location.scheme ||
|
|
@@ -152,18 +158,56 @@ module Net #:nodoc:
|
|
|
152
158
|
@uri.port != location.port)
|
|
153
159
|
raise "cannot redirect to a different host #{@uri} => #{location}"
|
|
154
160
|
end
|
|
155
|
-
new_req =
|
|
156
|
-
new_req
|
|
157
|
-
new_req.body_stream = req.body_stream
|
|
158
|
-
headers.each_pair { |key, value| new_req[key] = value } if headers
|
|
159
|
-
if (@user)
|
|
160
|
-
new_req.basic_auth @user, @pass
|
|
161
|
-
end
|
|
162
|
-
handle_request(new_req, limit - 1, &block)
|
|
161
|
+
new_req = clone_req(location.path, req, headers)
|
|
162
|
+
return handle_request(new_req, headers, limit - 1, &block)
|
|
163
163
|
else
|
|
164
164
|
response.error!
|
|
165
165
|
end
|
|
166
166
|
end
|
|
167
|
+
def clone_req(path, req, headers)
|
|
168
|
+
new_req = req.class.new(path)
|
|
169
|
+
new_req.body = req.body
|
|
170
|
+
new_req.body_stream = req.body_stream
|
|
171
|
+
headers.each_pair { |key, value| new_req[key] = value } if headers
|
|
172
|
+
return new_req
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
CNONCE = Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535))).slice(0, 8)
|
|
176
|
+
|
|
177
|
+
def digest_auth(request, user, password, response)
|
|
178
|
+
# based on http://segment7.net/projects/ruby/snippets/digest_auth.rb
|
|
179
|
+
@nonce_count = 0 if @nonce_count.nil?
|
|
180
|
+
@nonce_count += 1
|
|
181
|
+
|
|
182
|
+
raise "bad www-authenticate header" unless (response['www-authenticate'] =~ /^(\w+) (.*)/)
|
|
183
|
+
|
|
184
|
+
params = {}
|
|
185
|
+
$2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
|
|
186
|
+
|
|
187
|
+
a_1 = "#{user}:#{params['realm']}:#{password}"
|
|
188
|
+
a_2 = "#{request.method}:#{request.path}"
|
|
189
|
+
request_digest = ''
|
|
190
|
+
request_digest << Digest::MD5.hexdigest(a_1)
|
|
191
|
+
request_digest << ':' << params['nonce']
|
|
192
|
+
request_digest << ':' << ('%08x' % @nonce_count)
|
|
193
|
+
request_digest << ':' << CNONCE
|
|
194
|
+
request_digest << ':' << params['qop']
|
|
195
|
+
request_digest << ':' << Digest::MD5.hexdigest(a_2)
|
|
196
|
+
|
|
197
|
+
header = []
|
|
198
|
+
header << "Digest username=\"#{user}\""
|
|
199
|
+
header << "realm=\"#{params['realm']}\""
|
|
200
|
+
header << "nonce=\"#{params['nonce']}\""
|
|
201
|
+
header << "uri=\"#{request.path}\""
|
|
202
|
+
header << "cnonce=\"#{CNONCE}\""
|
|
203
|
+
header << "nc=#{'%08x' % @nonce_count}"
|
|
204
|
+
header << "qop=#{params['qop']}"
|
|
205
|
+
header << "response=\"#{Digest::MD5.hexdigest(request_digest)}\""
|
|
206
|
+
header << "algorithm=\"MD5\""
|
|
207
|
+
|
|
208
|
+
header = header.join(', ')
|
|
209
|
+
request['Authorization'] = header
|
|
210
|
+
end
|
|
167
211
|
end
|
|
168
212
|
|
|
169
213
|
|
|
@@ -187,6 +231,9 @@ module Net #:nodoc:
|
|
|
187
231
|
@curl.timeout = @http.read_timeout
|
|
188
232
|
@curl.follow_location = true
|
|
189
233
|
@curl.max_redirects = MAX_REDIRECTS
|
|
234
|
+
if disable_basic_auth
|
|
235
|
+
@curl.http_auth_types = Curl::CURLAUTH_DIGEST
|
|
236
|
+
end
|
|
190
237
|
end
|
|
191
238
|
@curl
|
|
192
239
|
end
|
|
@@ -210,11 +257,25 @@ module Net #:nodoc:
|
|
|
210
257
|
end
|
|
211
258
|
end
|
|
212
259
|
curl.perform
|
|
260
|
+
unless curl.response_code >= 200 && curl.response_code < 300
|
|
261
|
+
headers = curl.header_str.split(/\r?\n/)
|
|
262
|
+
raise Exception.new("Curl response #{headers[0]}")
|
|
263
|
+
end
|
|
213
264
|
curl.body_str
|
|
214
265
|
end
|
|
215
266
|
|
|
216
267
|
end
|
|
217
268
|
|
|
269
|
+
# Disable basic auth - to protect passwords from going in the clear
|
|
270
|
+
# through a man-in-the-middle attack.
|
|
271
|
+
def disable_basic_auth?
|
|
272
|
+
@handler.disable_basic_auth
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def disable_basic_auth=(value)
|
|
276
|
+
@handler.disable_basic_auth = value
|
|
277
|
+
end
|
|
278
|
+
|
|
218
279
|
# Seconds to wait until reading one block (by one system call).
|
|
219
280
|
# If the DAV object cannot read a block in this many seconds,
|
|
220
281
|
# it raises a TimeoutError exception.
|
data/net_dav.gemspec
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = %q{net_dav}
|
|
8
|
-
s.version = "0.
|
|
8
|
+
s.version = "0.3.0"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Miron Cuperman"]
|
|
12
|
-
s.date = %q{2009-11-
|
|
12
|
+
s.date = %q{2009-11-02}
|
|
13
13
|
s.default_executable = %q{dav}
|
|
14
14
|
s.description = %q{WebDAV client library in the style of Net::HTTP}
|
|
15
15
|
s.email = %q{c1.github@niftybox.net}
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: net_dav
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Miron Cuperman
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2009-11-
|
|
12
|
+
date: 2009-11-02 00:00:00 -08:00
|
|
13
13
|
default_executable: dav
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|