##// END OF EJS Templates
Link to watched issues list on my page....
Link to watched issues list on my page. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@2457 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r2376:f70be197e0ae
r2396:5bdd4291624c
Show More
discovery.rb
153 lines | 4.6 KiB | text/x-ruby | RubyLexer
Eric Davis
Unpacked OpenID gem. #699...
r2376
require 'openid/util'
require 'openid/fetchers'
require 'openid/yadis/constants'
require 'openid/yadis/parsehtml'
module OpenID
# Raised when a error occurs in the discovery process
class DiscoveryFailure < OpenIDError
attr_accessor :identity_url, :http_response
def initialize(message, http_response)
super(message)
@identity_url = nil
@http_response = http_response
end
end
module Yadis
# Contains the result of performing Yadis discovery on a URI
class DiscoveryResult
# The result of following redirects from the request_uri
attr_accessor :normalize_uri
# The URI from which the response text was returned (set to
# nil if there was no XRDS document found)
attr_accessor :xrds_uri
# The content-type returned with the response_text
attr_accessor :content_type
# The document returned from the xrds_uri
attr_accessor :response_text
attr_accessor :request_uri, :normalized_uri
def initialize(request_uri)
# Initialize the state of the object
#
# sets all attributes to None except the request_uri
@request_uri = request_uri
@normalized_uri = nil
@xrds_uri = nil
@content_type = nil
@response_text = nil
end
# Was the Yadis protocol's indirection used?
def used_yadis_location?
return @normalized_uri != @xrds_uri
end
# Is the response text supposed to be an XRDS document?
def is_xrds
return (used_yadis_location?() or
@content_type == YADIS_CONTENT_TYPE)
end
end
# Discover services for a given URI.
#
# uri: The identity URI as a well-formed http or https URI. The
# well-formedness and the protocol are not checked, but the
# results of this function are undefined if those properties do
# not hold.
#
# returns a DiscoveryResult object
#
# Raises DiscoveryFailure when the HTTP response does not have
# a 200 code.
def self.discover(uri)
result = DiscoveryResult.new(uri)
begin
resp = OpenID.fetch(uri, nil, {'Accept' => YADIS_ACCEPT_HEADER})
rescue Exception
raise DiscoveryFailure.new("Failed to fetch identity URL #{uri} : #{$!}", $!)
end
if resp.code != "200" and resp.code != "206"
raise DiscoveryFailure.new(
"HTTP Response status from identity URL host is not \"200\"."\
"Got status #{resp.code.inspect} for #{resp.final_url}", resp)
end
# Note the URL after following redirects
result.normalized_uri = resp.final_url
# Attempt to find out where to go to discover the document or if
# we already have it
result.content_type = resp['content-type']
result.xrds_uri = self.where_is_yadis?(resp)
if result.xrds_uri and result.used_yadis_location?
begin
resp = OpenID.fetch(result.xrds_uri)
rescue
raise DiscoveryFailure.new("Failed to fetch Yadis URL #{result.xrds_uri} : #{$!}", $!)
end
if resp.code != "200" and resp.code != "206"
exc = DiscoveryFailure.new(
"HTTP Response status from Yadis host is not \"200\". " +
"Got status #{resp.code.inspect} for #{resp.final_url}", resp)
exc.identity_url = result.normalized_uri
raise exc
end
result.content_type = resp['content-type']
end
result.response_text = resp.body
return result
end
# Given a HTTPResponse, return the location of the Yadis
# document.
#
# May be the URL just retrieved, another URL, or None, if I
# can't find any.
#
# [non-blocking]
def self.where_is_yadis?(resp)
# Attempt to find out where to go to discover the document or if
# we already have it
content_type = resp['content-type']
# According to the spec, the content-type header must be an
# exact match, or else we have to look for an indirection.
if (!content_type.nil? and !content_type.to_s.empty? and
content_type.split(';', 2)[0].downcase == YADIS_CONTENT_TYPE)
return resp.final_url
else
# Try the header
yadis_loc = resp[YADIS_HEADER_NAME.downcase]
if yadis_loc.nil?
# Parse as HTML if the header is missing.
#
# XXX: do we want to do something with content-type, like
# have a whitelist or a blacklist (for detecting that it's
# HTML)?
yadis_loc = Yadis.html_yadis_location(resp.body)
end
end
return yadis_loc
end
end
end