class HTTPClient::DigestAuth

Used in WWWAuth.
Authentication filter for handling DigestAuth negotiation.

def calc_cred(method, uri, user, passwd, param)

supported algorithm: MD5 only for now
Thanks!
http://tools.assembla.com/breakout/wiki/DigestForSoap
this method is implemented by sromano and posted to
def calc_cred(method, uri, user, passwd, param)
  a_1 = "#{user}:#{param['realm']}:#{passwd}"
  a_2 = "#{method}:#{uri.path}"
  @nonce_count += 1
  message_digest = []
  message_digest << Digest::MD5.hexdigest(a_1)
  message_digest << param['nonce']
  message_digest << ('%08x' % @nonce_count)
  message_digest << param['nonce']
  message_digest << param['qop']
  message_digest << Digest::MD5.hexdigest(a_2)
  header = []
  header << "username=\"#{user}\""
  header << "realm=\"#{param['realm']}\""
  header << "nonce=\"#{param['nonce']}\""
  header << "uri=\"#{uri.path}\""
  header << "cnonce=\"#{param['nonce']}\""
  header << "nc=#{'%08x' % @nonce_count}"
  header << "qop=\"#{param['qop']}\""
  header << "response=\"#{Digest::MD5.hexdigest(message_digest.join(":"))}\""
  header << "algorithm=\"MD5\""
  header << "opaque=\"#{param['opaque']}\"" if param.key?('opaque')
  header.join(", ")
end

def challenge(uri, param_str)

Challenge handler: remember URL and challenge token for response.
def challenge(uri, param_str)
  @challenge[uri] = parse_challenge_param(param_str)
  true
end

def get(req)

* child page of defined credential
* child page of challengeable(got *Authenticate before) uri and,
It sends cred only when a given uri is;
Response handler: returns credential.
def get(req)
  target_uri = req.header.request_uri
  param = Util.hash_find_value(@challenge) { |uri, v|
    Util.uri_part_of(target_uri, uri)
  }
  return nil unless param
  user, passwd = Util.hash_find_value(@auth) { |uri, auth_data|
    Util.uri_part_of(target_uri, uri)
  }
  return nil unless user
  uri = req.header.request_uri
  calc_cred(req.header.request_method, uri, user, passwd, param)
end

def initialize

Creates new DigestAuth filter.
def initialize
  @auth = {}
  @challenge = {}
  @nonce_count = 0
  @scheme = "Digest"
end

def parse_challenge_param(param_str)

def parse_challenge_param(param_str)
  param = {}
  param_str.scan(/\s*([^\,]+(?:\\.[^\,]*)*)/).each do |str|
    key, value = str[0].scan(/\A([^=]+)=(.*)\z/)[0]
    if /\A"(.*)"\z/ =~ value
      value = $1.gsub(/\\(.)/, '\1')
    end
    param[key] = value
  end
  param
end

def reset_challenge

server sends '*Authentication' again.
Resets challenge state. Do not send '*Authorization' header until the
def reset_challenge
  @challenge.clear
end

def set(uri, user, passwd)

uri == nil is ignored.
Set authentication credential.
def set(uri, user, passwd)
  if uri
    uri = Util.uri_dirname(uri)
    @auth[uri] = [user, passwd]
  end
end