Class: Net::DAV::NetHttpHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/net/dav.rb

Direct Known Subclasses

CurlHandler

Constant Summary collapse

CNONCE =
Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535))).slice(0, 8)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri) ⇒ NetHttpHandler

Returns a new instance of NetHttpHandler.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/net/dav.rb', line 38

def initialize(uri)
  @disable_basic_auth = false
  @uri = uri
  case @uri.scheme
  when "http"
    @http = Net::HTTP.new(@uri.host, @uri.port)
  when "https"
    @http = Net::HTTP.new(@uri.host, @uri.port)
    @http.use_ssl = true
    self.verify_server = true
  else
    raise "unknown uri scheme"
  end
end

Instance Attribute Details

#disable_basic_authObject

Returns the value of attribute disable_basic_auth.



26
27
28
# File 'lib/net/dav.rb', line 26

def disable_basic_auth
  @disable_basic_auth
end

#last_statusObject (readonly)

Returns the value of attribute last_status.



27
28
29
# File 'lib/net/dav.rb', line 27

def last_status
  @last_status
end

#pass=(value) ⇒ Object (writeonly)

Sets the attribute pass

Parameters:

  • value

    the value to set the attribute pass to.



24
25
26
# File 'lib/net/dav.rb', line 24

def pass=(value)
  @pass = value
end

#user=(value) ⇒ Object (writeonly)

Sets the attribute user

Parameters:

  • value

    the value to set the attribute user to.



24
25
26
# File 'lib/net/dav.rb', line 24

def user=(value)
  @user = value
end

Instance Method Details

#ca_file(ca_file) ⇒ Object

path of a CA certification file in PEM format. The file can contain several CA certificates.



274
275
276
# File 'lib/net/dav.rb', line 274

def ca_file(ca_file)
  @http.ca_file  = ca_file
end

#cert_file(cert_file) ⇒ Object



257
258
259
260
261
262
# File 'lib/net/dav.rb', line 257

def cert_file(cert_file)
  # expects a OpenSSL::X509::Certificate object as client certificate
  @http.cert  = OpenSSL::X509::Certificate.new(File.read(cert_file))
  #puts @http.cert.not_after
  #puts @http.cert.subject
end

#cert_key(cert_file, cert_file_password) ⇒ Object



264
265
266
267
268
269
270
271
# File 'lib/net/dav.rb', line 264

def cert_key(cert_file, cert_file_password)
  # expects a OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object
  if cert_file_password then
    @http.key = OpenSSL::PKey::RSA.new(File.read(cert_file),cert_file_password)
  else
    @http.key = OpenSSL::PKey::RSA.new(File.read(cert_file))
  end
end

#clone_req(path, req, headers) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/net/dav.rb', line 207

def clone_req(path, req, headers)
  new_req = req.class.new(path)
  new_req.body = req.body if req.body
  if (req.body_stream)
    req.body_stream.rewind
    new_req.body_stream = req.body_stream
  end
  new_req.content_length = req.content_length if req.content_length
  headers.each_pair { |key, value| new_req[key] = value } if headers
  new_req.content_type = req.content_type if req.content_type
  return new_req
end

#digest_auth(request, user, password, response) ⇒ Object



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
# File 'lib/net/dav.rb', line 222

def digest_auth(request, user, password, response)
  # based on http://segment7.net/projects/ruby/snippets/digest_auth.rb
  @nonce_count = 0 if @nonce_count.nil?
  @nonce_count += 1

  raise "bad www-authenticate header" unless (response['www-authenticate'] =~ /^(\w+) (.*)/)

  params = {}
  $2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }

  a_1 = "#{user}:#{params['realm']}:#{password}"
  a_2 = "#{request.method}:#{request.path}"
  request_digest = ''
  request_digest << Digest::MD5.hexdigest(a_1)
  request_digest << ':' << params['nonce']
  request_digest << ':' << ('%08x' % @nonce_count)
  request_digest << ':' << CNONCE
  request_digest << ':' << params['qop']
  request_digest << ':' << Digest::MD5.hexdigest(a_2)

  header = []
  header << "Digest username=\"#{user}\""
  header << "realm=\"#{params['realm']}\""
  header << "nonce=\"#{params['nonce']}\""
  header << "uri=\"#{request.path}\""
  header << "cnonce=\"#{CNONCE}\""
  header << "nc=#{'%08x' % @nonce_count}"
  header << "qop=#{params['qop']}"
  header << "response=\"#{Digest::MD5.hexdigest(request_digest)}\""
  header << "algorithm=\"MD5\""

  header = header.join(', ')
  request['Authorization'] = header
end

#handle_request(req, headers, limit = MAX_REDIRECTS, &block) ⇒ Object

Raises:

  • (ArgumentError)


154
155
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/net/dav.rb', line 154

def handle_request(req, headers, limit = MAX_REDIRECTS, &block)
  # You should choose better exception.
  raise ArgumentError, 'HTTP redirect too deep' if limit == 0

  case @authorization
  when :basic
    req.basic_auth @user, @pass
  when :digest
    digest_auth(req, @user, @pass, response)
  end

  response = nil
  if block
    @http.request(req) {|res|
      # Only start returning a body if we will not retry
      res.read_body nil, &block if !res.is_a?(Net::HTTPUnauthorized) && !res.is_a?(Net::HTTPRedirection)
      response = res
    }
  else
    response = @http.request(req)
  end

  @last_status = response.code.to_i
  case response
  when Net::HTTPSuccess     then
    return response
  when Net::HTTPUnauthorized     then
    response.error! unless @user
    response.error! if req['authorization']
    new_req = clone_req(req.path, req, headers)
    if response['www-authenticate'] =~ /^basic/i
      if disable_basic_auth
        raise "server requested basic auth, but that is disabled"
      end
      @authorization = :basic
    else
      @authorization = :digest
    end
    return handle_request(req, headers, limit - 1, &block)
  when Net::HTTPRedirection then
    location = URI.parse(response['location'])
    if (@uri.scheme != location.scheme ||
        @uri.host != location.host ||
        @uri.port != location.port)
      raise ArgumentError, "cannot redirect to a different host #{@uri} => #{location}"
    end
    new_req = clone_req(location.path, req, headers)
    return handle_request(new_req, headers, limit - 1, &block)
  else
    response.error!
  end
end

#open_timeoutObject



65
66
67
# File 'lib/net/dav.rb', line 65

def open_timeout
  @http.read_timeout
end

#open_timeout=(sec) ⇒ Object



69
70
71
# File 'lib/net/dav.rb', line 69

def open_timeout=(sec)
  @http.read_timeout = sec
end

#read_timeoutObject



57
58
59
# File 'lib/net/dav.rb', line 57

def read_timeout
  @http.read_timeout
end

#read_timeout=(sec) ⇒ Object



61
62
63
# File 'lib/net/dav.rb', line 61

def read_timeout=(sec)
  @http.read_timeout = sec
end

#request(verb, path, body, headers) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/net/dav.rb', line 123

def request(verb, path, body, headers)
  headers ||= {}
  headers = {"User-Agent" => "Ruby"}.merge(headers)
  req =
    case verb
    when :propfind
      Net::HTTP::Propfind.new(path)
    when :mkcol
      Net::HTTP::Mkcol.new(path)
    when :delete
      Net::HTTP::Delete.new(path)
    when :move
      Net::HTTP::Move.new(path)
    when :copy
      Net::HTTP::Copy.new(path)
    when :proppatch
      Net::HTTP::Proppatch.new(path)
    when :lock
      Net::HTTP::Lock.new(path)
    when :unlock
      Net::HTTP::Unlock.new(path)
    else
      raise "unkown verb #{verb}"
    end
  req.body = body
  headers.each_pair { |key, value| req[key] = value } if headers
  req.content_type = 'text/xml; charset="utf-8"'
  res = handle_request(req, headers)
  res
end

#request_returning_body(verb, path, headers, &block) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/net/dav.rb', line 108

def request_returning_body(verb, path, headers, &block)
  headers ||= {}
  headers = {"User-Agent" => "Ruby"}.merge(headers)
  req =
    case verb
    when :get
      Net::HTTP::Get.new(path)
    else
      raise "unkown returning_body verb #{verb}"
    end
  headers.each_pair { |key, value| req[key] = value } if headers
  res = handle_request(req, headers, MAX_REDIRECTS, &block)
  res.body
end

#request_sending_body(verb, path, body, headers) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/net/dav.rb', line 91

def request_sending_body(verb, path, body, headers)
  headers ||= {}
  headers = {"User-Agent" => "Ruby"}.merge(headers)
  req =
    case verb
    when :put
      Net::HTTP::Put.new(path)
    else
      raise "unkown sending_body verb #{verb}"
    end
  req.body = body
  headers.each_pair { |key, value| req[key] = value } if headers
  req.content_type = 'application/octet-stream'
  res = handle_request(req, headers)
  res
end

#request_sending_stream(verb, path, stream, length, headers) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/net/dav.rb', line 73

def request_sending_stream(verb, path, stream, length, headers)
  headers ||= {}
  headers = {"User-Agent" => "Ruby"}.merge(headers)
  req =
    case verb
    when :put
      Net::HTTP::Put.new(path)
    else
      raise "unkown sending_stream verb #{verb}"
    end
  req.body_stream = stream
  req.content_length = length
  headers.each_pair { |key, value| req[key] = value } if headers
  req.content_type = 'application/octet-stream'
  res = handle_request(req, headers)
  res
end

#start(&block) ⇒ Object



53
54
55
# File 'lib/net/dav.rb', line 53

def start(&block)
  @http.start(&block)
end

#verify_callback=(callback) ⇒ Object



30
31
32
# File 'lib/net/dav.rb', line 30

def verify_callback=(callback)
  @http.verify_callback = callback
end

#verify_server=(value) ⇒ Object



34
35
36
# File 'lib/net/dav.rb', line 34

def verify_server=(value)
  @http.verify_mode = value ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
end