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.


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

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


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

def disable_basic_auth
  @disable_basic_auth
end

#last_statusObject (readonly)

Returns the value of attribute last_status


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

def last_status
  @last_status
end

#pass=(value) ⇒ Object (writeonly)

Sets the attribute pass

Parameters:

  • value

    the value to set the attribute pass to.


22
23
24
# File 'lib/net/dav.rb', line 22

def pass=(value)
  @pass = value
end

#user=(value) ⇒ Object (writeonly)

Sets the attribute user

Parameters:

  • value

    the value to set the attribute user to.


22
23
24
# File 'lib/net/dav.rb', line 22

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.


272
273
274
# File 'lib/net/dav.rb', line 272

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

#cert_file(cert_file) ⇒ Object


255
256
257
258
259
260
# File 'lib/net/dav.rb', line 255

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


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

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


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

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


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

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)

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

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


63
64
65
# File 'lib/net/dav.rb', line 63

def open_timeout
  @http.read_timeout
end

#open_timeout=(sec) ⇒ Object


67
68
69
# File 'lib/net/dav.rb', line 67

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

#read_timeoutObject


55
56
57
# File 'lib/net/dav.rb', line 55

def read_timeout
  @http.read_timeout
end

#read_timeout=(sec) ⇒ Object


59
60
61
# File 'lib/net/dav.rb', line 59

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

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


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

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


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

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


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

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


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

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


51
52
53
# File 'lib/net/dav.rb', line 51

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

#verify_callback=(callback) ⇒ Object


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

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

#verify_server=(value) ⇒ Object


32
33
34
# File 'lib/net/dav.rb', line 32

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