require 'openid/fetchers' module OpenID module Yadis module XRI # The '(' is for cross-reference authorities, and hopefully has a # matching ')' somewhere. XRI_AUTHORITIES = ["!", "=", "@", "+", "$", "("] def self.identifier_scheme(identifier) if (!identifier.nil? and identifier.length > 0 and (identifier.match('^xri://') or XRI_AUTHORITIES.member?(identifier[0].chr))) return :xri else return :uri end end # Transform an XRI reference to an IRI reference. Note this is # not not idempotent, so do not apply this to an identifier more # than once. XRI Syntax section 2.3.1 def self.to_iri_normal(xri) iri = xri.dup iri.insert(0, 'xri://') if not iri.match('^xri://') return escape_for_iri(iri) end # Note this is not not idempotent, so do not apply this more than # once. XRI Syntax section 2.3.2 def self.escape_for_iri(xri) esc = xri.dup # encode all % esc.gsub!(/%/, '%25') esc.gsub!(/\((.*?)\)/) { |xref_match| xref_match.gsub(/[\/\?\#]/) { |char_match| CGI::escape(char_match) } } return esc end # Transform an XRI reference to a URI reference. Note this is not # not idempotent, so do not apply this to an identifier more than # once. XRI Syntax section 2.3.1 def self.to_uri_normal(xri) return iri_to_uri(to_iri_normal(xri)) end # RFC 3987 section 3.1 def self.iri_to_uri(iri) uri = iri.dup # for char in ucschar or iprivate # convert each char to %HH%HH%HH (as many %HH as octets) return uri end def self.provider_is_authoritative(provider_id, canonical_id) lastbang = canonical_id.rindex('!') return false unless lastbang parent = canonical_id[0...lastbang] return parent == provider_id end def self.root_authority(xri) xri = xri[6..-1] if xri.index('xri://') == 0 authority = xri.split('/', 2)[0] if authority[0].chr == '(' root = authority[0...authority.index(')')+1] elsif XRI_AUTHORITIES.member?(authority[0].chr) root = authority[0].chr else root = authority.split(/[!*]/)[0] end self.make_xri(root) end def self.make_xri(xri) if xri.index('xri://') != 0 xri = 'xri://' + xri end return xri end end end end