pelle-ruby-openid 2.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +215 -0
- data/CHANGES-2.1.0 +36 -0
- data/INSTALL +47 -0
- data/LICENSE +210 -0
- data/NOTICE +2 -0
- data/README +82 -0
- data/UPGRADE +127 -0
- data/VERSION +1 -0
- data/examples/README +32 -0
- data/examples/active_record_openid_store/README +58 -0
- data/examples/active_record_openid_store/XXX_add_open_id_store_to_db.rb +24 -0
- data/examples/active_record_openid_store/XXX_upgrade_open_id_store.rb +26 -0
- data/examples/active_record_openid_store/init.rb +8 -0
- data/examples/active_record_openid_store/lib/association.rb +10 -0
- data/examples/active_record_openid_store/lib/nonce.rb +3 -0
- data/examples/active_record_openid_store/lib/open_id_setting.rb +4 -0
- data/examples/active_record_openid_store/lib/openid_ar_store.rb +57 -0
- data/examples/active_record_openid_store/test/store_test.rb +212 -0
- data/examples/discover +49 -0
- data/examples/rails_openid/README +153 -0
- data/examples/rails_openid/Rakefile +10 -0
- data/examples/rails_openid/app/controllers/application.rb +4 -0
- data/examples/rails_openid/app/controllers/consumer_controller.rb +122 -0
- data/examples/rails_openid/app/controllers/login_controller.rb +45 -0
- data/examples/rails_openid/app/controllers/server_controller.rb +265 -0
- data/examples/rails_openid/app/helpers/application_helper.rb +3 -0
- data/examples/rails_openid/app/helpers/login_helper.rb +2 -0
- data/examples/rails_openid/app/helpers/server_helper.rb +9 -0
- data/examples/rails_openid/app/views/consumer/index.rhtml +81 -0
- data/examples/rails_openid/app/views/layouts/server.rhtml +68 -0
- data/examples/rails_openid/app/views/login/index.rhtml +56 -0
- data/examples/rails_openid/app/views/server/decide.rhtml +26 -0
- data/examples/rails_openid/config/boot.rb +19 -0
- data/examples/rails_openid/config/database.yml +74 -0
- data/examples/rails_openid/config/environment.rb +54 -0
- data/examples/rails_openid/config/environments/development.rb +19 -0
- data/examples/rails_openid/config/environments/production.rb +19 -0
- data/examples/rails_openid/config/environments/test.rb +19 -0
- data/examples/rails_openid/config/routes.rb +24 -0
- data/examples/rails_openid/doc/README_FOR_APP +2 -0
- data/examples/rails_openid/public/.htaccess +40 -0
- data/examples/rails_openid/public/404.html +8 -0
- data/examples/rails_openid/public/500.html +8 -0
- data/examples/rails_openid/public/dispatch.cgi +12 -0
- data/examples/rails_openid/public/dispatch.fcgi +26 -0
- data/examples/rails_openid/public/dispatch.rb +12 -0
- data/examples/rails_openid/public/favicon.ico +0 -0
- data/examples/rails_openid/public/images/openid_login_bg.gif +0 -0
- data/examples/rails_openid/public/javascripts/controls.js +750 -0
- data/examples/rails_openid/public/javascripts/dragdrop.js +584 -0
- data/examples/rails_openid/public/javascripts/effects.js +854 -0
- data/examples/rails_openid/public/javascripts/prototype.js +1785 -0
- data/examples/rails_openid/public/robots.txt +1 -0
- data/examples/rails_openid/script/about +3 -0
- data/examples/rails_openid/script/breakpointer +3 -0
- data/examples/rails_openid/script/console +3 -0
- data/examples/rails_openid/script/destroy +3 -0
- data/examples/rails_openid/script/generate +3 -0
- data/examples/rails_openid/script/performance/benchmarker +3 -0
- data/examples/rails_openid/script/performance/profiler +3 -0
- data/examples/rails_openid/script/plugin +3 -0
- data/examples/rails_openid/script/process/reaper +3 -0
- data/examples/rails_openid/script/process/spawner +3 -0
- data/examples/rails_openid/script/process/spinner +3 -0
- data/examples/rails_openid/script/runner +3 -0
- data/examples/rails_openid/script/server +3 -0
- data/examples/rails_openid/test/functional/login_controller_test.rb +18 -0
- data/examples/rails_openid/test/functional/server_controller_test.rb +18 -0
- data/examples/rails_openid/test/test_helper.rb +28 -0
- data/lib/hmac/hmac.rb +112 -0
- data/lib/hmac/sha1.rb +11 -0
- data/lib/hmac/sha2.rb +25 -0
- data/lib/openid/association.rb +249 -0
- data/lib/openid/consumer/associationmanager.rb +344 -0
- data/lib/openid/consumer/checkid_request.rb +186 -0
- data/lib/openid/consumer/discovery.rb +498 -0
- data/lib/openid/consumer/discovery_manager.rb +123 -0
- data/lib/openid/consumer/html_parse.rb +134 -0
- data/lib/openid/consumer/idres.rb +523 -0
- data/lib/openid/consumer/responses.rb +148 -0
- data/lib/openid/consumer.rb +395 -0
- data/lib/openid/cryptutil.rb +97 -0
- data/lib/openid/dh.rb +89 -0
- data/lib/openid/extension.rb +39 -0
- data/lib/openid/extensions/ax.rb +516 -0
- data/lib/openid/extensions/oauth.rb +91 -0
- data/lib/openid/extensions/pape.rb +179 -0
- data/lib/openid/extensions/sreg.rb +277 -0
- data/lib/openid/extras.rb +11 -0
- data/lib/openid/fetchers.rb +238 -0
- data/lib/openid/kvform.rb +136 -0
- data/lib/openid/kvpost.rb +58 -0
- data/lib/openid/message.rb +553 -0
- data/lib/openid/protocolerror.rb +8 -0
- data/lib/openid/server.rb +1544 -0
- data/lib/openid/store/filesystem.rb +271 -0
- data/lib/openid/store/interface.rb +75 -0
- data/lib/openid/store/memcache.rb +107 -0
- data/lib/openid/store/memory.rb +84 -0
- data/lib/openid/store/nonce.rb +68 -0
- data/lib/openid/trustroot.rb +349 -0
- data/lib/openid/urinorm.rb +75 -0
- data/lib/openid/util.rb +110 -0
- data/lib/openid/yadis/accept.rb +148 -0
- data/lib/openid/yadis/constants.rb +21 -0
- data/lib/openid/yadis/discovery.rb +153 -0
- data/lib/openid/yadis/filters.rb +205 -0
- data/lib/openid/yadis/htmltokenizer.rb +305 -0
- data/lib/openid/yadis/parsehtml.rb +45 -0
- data/lib/openid/yadis/services.rb +42 -0
- data/lib/openid/yadis/xrds.rb +155 -0
- data/lib/openid/yadis/xri.rb +90 -0
- data/lib/openid/yadis/xrires.rb +106 -0
- data/lib/openid.rb +20 -0
- data/setup.rb +1551 -0
- data/test/data/accept.txt +124 -0
- data/test/data/dh.txt +29 -0
- data/test/data/example-xrds.xml +14 -0
- data/test/data/linkparse.txt +587 -0
- data/test/data/n2b64 +650 -0
- data/test/data/test1-discover.txt +137 -0
- data/test/data/test1-parsehtml.txt +152 -0
- data/test/data/test_discover/malformed_meta_tag.html +19 -0
- data/test/data/test_discover/openid.html +11 -0
- data/test/data/test_discover/openid2.html +11 -0
- data/test/data/test_discover/openid2_xrds.xml +12 -0
- data/test/data/test_discover/openid2_xrds_no_local_id.xml +11 -0
- data/test/data/test_discover/openid_1_and_2.html +11 -0
- data/test/data/test_discover/openid_1_and_2_xrds.xml +16 -0
- data/test/data/test_discover/openid_1_and_2_xrds_bad_delegate.xml +17 -0
- data/test/data/test_discover/openid_and_yadis.html +12 -0
- data/test/data/test_discover/openid_no_delegate.html +10 -0
- data/test/data/test_discover/yadis_0entries.xml +12 -0
- data/test/data/test_discover/yadis_2_bad_local_id.xml +15 -0
- data/test/data/test_discover/yadis_2entries_delegate.xml +22 -0
- data/test/data/test_discover/yadis_2entries_idp.xml +21 -0
- data/test/data/test_discover/yadis_another_delegate.xml +14 -0
- data/test/data/test_discover/yadis_idp.xml +12 -0
- data/test/data/test_discover/yadis_idp_delegate.xml +13 -0
- data/test/data/test_discover/yadis_no_delegate.xml +11 -0
- data/test/data/test_xrds/=j3h.2007.11.14.xrds +25 -0
- data/test/data/test_xrds/README +12 -0
- data/test/data/test_xrds/delegated-20060809-r1.xrds +34 -0
- data/test/data/test_xrds/delegated-20060809-r2.xrds +34 -0
- data/test/data/test_xrds/delegated-20060809.xrds +34 -0
- data/test/data/test_xrds/no-xrd.xml +7 -0
- data/test/data/test_xrds/not-xrds.xml +2 -0
- data/test/data/test_xrds/prefixsometimes.xrds +34 -0
- data/test/data/test_xrds/ref.xrds +109 -0
- data/test/data/test_xrds/sometimesprefix.xrds +34 -0
- data/test/data/test_xrds/spoof1.xrds +25 -0
- data/test/data/test_xrds/spoof2.xrds +25 -0
- data/test/data/test_xrds/spoof3.xrds +37 -0
- data/test/data/test_xrds/status222.xrds +9 -0
- data/test/data/test_xrds/subsegments.xrds +58 -0
- data/test/data/test_xrds/valid-populated-xrds.xml +39 -0
- data/test/data/trustroot.txt +153 -0
- data/test/data/urinorm.txt +79 -0
- data/test/discoverdata.rb +131 -0
- data/test/test_accept.rb +170 -0
- data/test/test_association.rb +266 -0
- data/test/test_associationmanager.rb +917 -0
- data/test/test_ax.rb +648 -0
- data/test/test_checkid_request.rb +294 -0
- data/test/test_consumer.rb +257 -0
- data/test/test_cryptutil.rb +119 -0
- data/test/test_dh.rb +86 -0
- data/test/test_discover.rb +838 -0
- data/test/test_discovery_manager.rb +262 -0
- data/test/test_extension.rb +46 -0
- data/test/test_extras.rb +35 -0
- data/test/test_fetchers.rb +538 -0
- data/test/test_filters.rb +270 -0
- data/test/test_idres.rb +963 -0
- data/test/test_kvform.rb +165 -0
- data/test/test_kvpost.rb +65 -0
- data/test/test_linkparse.rb +101 -0
- data/test/test_message.rb +1116 -0
- data/test/test_nonce.rb +89 -0
- data/test/test_oauth.rb +175 -0
- data/test/test_openid_yadis.rb +178 -0
- data/test/test_pape.rb +247 -0
- data/test/test_parsehtml.rb +80 -0
- data/test/test_responses.rb +63 -0
- data/test/test_server.rb +2457 -0
- data/test/test_sreg.rb +479 -0
- data/test/test_stores.rb +298 -0
- data/test/test_trustroot.rb +113 -0
- data/test/test_urinorm.rb +35 -0
- data/test/test_util.rb +145 -0
- data/test/test_xrds.rb +169 -0
- data/test/test_xri.rb +48 -0
- data/test/test_xrires.rb +63 -0
- data/test/test_yadis_discovery.rb +220 -0
- data/test/testutil.rb +127 -0
- data/test/util.rb +53 -0
- metadata +316 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
|
|
2
|
+
require 'openid/yadis/filters'
|
|
3
|
+
require 'openid/yadis/discovery'
|
|
4
|
+
require 'openid/yadis/xrds'
|
|
5
|
+
|
|
6
|
+
module OpenID
|
|
7
|
+
module Yadis
|
|
8
|
+
def Yadis.get_service_endpoints(input_url, flt=nil)
|
|
9
|
+
# Perform the Yadis protocol on the input URL and return an
|
|
10
|
+
# iterable of resulting endpoint objects.
|
|
11
|
+
#
|
|
12
|
+
# @param flt: A filter object or something that is convertable
|
|
13
|
+
# to a filter object (using mkFilter) that will be used to
|
|
14
|
+
# generate endpoint objects. This defaults to generating
|
|
15
|
+
# BasicEndpoint objects.
|
|
16
|
+
result = Yadis.discover(input_url)
|
|
17
|
+
begin
|
|
18
|
+
endpoints = Yadis.apply_filter(result.normalized_uri,
|
|
19
|
+
result.response_text, flt)
|
|
20
|
+
rescue XRDSError => err
|
|
21
|
+
raise DiscoveryFailure.new(err.to_s, nil)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
return [result.normalized_uri, endpoints]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def Yadis.apply_filter(normalized_uri, xrd_data, flt=nil)
|
|
28
|
+
# Generate an iterable of endpoint objects given this input data,
|
|
29
|
+
# presumably from the result of performing the Yadis protocol.
|
|
30
|
+
|
|
31
|
+
flt = Yadis.make_filter(flt)
|
|
32
|
+
et = Yadis.parseXRDS(xrd_data)
|
|
33
|
+
|
|
34
|
+
endpoints = []
|
|
35
|
+
each_service(et) { |service_element|
|
|
36
|
+
endpoints += flt.get_service_endpoints(normalized_uri, service_element)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return endpoints
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
require 'rexml/document'
|
|
2
|
+
require 'rexml/element'
|
|
3
|
+
require 'rexml/xpath'
|
|
4
|
+
|
|
5
|
+
require 'openid/yadis/xri'
|
|
6
|
+
|
|
7
|
+
module OpenID
|
|
8
|
+
module Yadis
|
|
9
|
+
|
|
10
|
+
XRD_NS_2_0 = 'xri://$xrd*($v*2.0)'
|
|
11
|
+
XRDS_NS = 'xri://$xrds'
|
|
12
|
+
|
|
13
|
+
XRDS_NAMESPACES = {
|
|
14
|
+
'xrds' => XRDS_NS,
|
|
15
|
+
'xrd' => XRD_NS_2_0,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class XRDSError < StandardError; end
|
|
19
|
+
|
|
20
|
+
# Raised when there's an assertion in the XRDS that it does not
|
|
21
|
+
# have the authority to make.
|
|
22
|
+
class XRDSFraud < XRDSError
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def Yadis::get_canonical_id(iname, xrd_tree)
|
|
26
|
+
# Return the CanonicalID from this XRDS document.
|
|
27
|
+
#
|
|
28
|
+
# @param iname: the XRI being resolved.
|
|
29
|
+
# @type iname: unicode
|
|
30
|
+
#
|
|
31
|
+
# @param xrd_tree: The XRDS output from the resolver.
|
|
32
|
+
#
|
|
33
|
+
# @returns: The XRI CanonicalID or None.
|
|
34
|
+
# @returntype: unicode or None
|
|
35
|
+
|
|
36
|
+
xrd_list = []
|
|
37
|
+
REXML::XPath::match(xrd_tree.root, '/xrds:XRDS/xrd:XRD', XRDS_NAMESPACES).each { |el|
|
|
38
|
+
xrd_list << el
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
xrd_list.reverse!
|
|
42
|
+
|
|
43
|
+
cid_elements = []
|
|
44
|
+
|
|
45
|
+
if !xrd_list.empty?
|
|
46
|
+
xrd_list[0].elements.each { |e|
|
|
47
|
+
if !e.respond_to?('name')
|
|
48
|
+
next
|
|
49
|
+
end
|
|
50
|
+
if e.name == 'CanonicalID'
|
|
51
|
+
cid_elements << e
|
|
52
|
+
end
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
cid_element = cid_elements[0]
|
|
57
|
+
|
|
58
|
+
if !cid_element
|
|
59
|
+
return nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
canonicalID = XRI.make_xri(cid_element.text)
|
|
63
|
+
|
|
64
|
+
childID = canonicalID.downcase
|
|
65
|
+
|
|
66
|
+
xrd_list[1..-1].each { |xrd|
|
|
67
|
+
parent_sought = childID[0...childID.rindex('!')]
|
|
68
|
+
|
|
69
|
+
parent = XRI.make_xri(xrd.elements["CanonicalID"].text)
|
|
70
|
+
|
|
71
|
+
if parent_sought != parent.downcase
|
|
72
|
+
raise XRDSFraud.new(sprintf("%s can not come from %s", parent_sought,
|
|
73
|
+
parent))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
childID = parent_sought
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
root = XRI.root_authority(iname)
|
|
80
|
+
if not XRI.provider_is_authoritative(root, childID)
|
|
81
|
+
raise XRDSFraud.new(sprintf("%s can not come from root %s", childID, root))
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
return canonicalID
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class XRDSError < StandardError
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def Yadis::parseXRDS(text)
|
|
91
|
+
if text.nil?
|
|
92
|
+
raise XRDSError.new("Not an XRDS document.")
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
begin
|
|
96
|
+
d = REXML::Document.new(text)
|
|
97
|
+
rescue RuntimeError => why
|
|
98
|
+
raise XRDSError.new("Not an XRDS document. Failed to parse XML.")
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
if is_xrds?(d)
|
|
102
|
+
return d
|
|
103
|
+
else
|
|
104
|
+
raise XRDSError.new("Not an XRDS document.")
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def Yadis::is_xrds?(xrds_tree)
|
|
109
|
+
xrds_root = xrds_tree.root
|
|
110
|
+
return (!xrds_root.nil? and
|
|
111
|
+
xrds_root.name == 'XRDS' and
|
|
112
|
+
xrds_root.namespace == XRDS_NS)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def Yadis::get_yadis_xrd(xrds_tree)
|
|
116
|
+
REXML::XPath.each(xrds_tree.root,
|
|
117
|
+
'/xrds:XRDS/xrd:XRD[last()]',
|
|
118
|
+
XRDS_NAMESPACES) { |el|
|
|
119
|
+
return el
|
|
120
|
+
}
|
|
121
|
+
raise XRDSError.new("No XRD element found.")
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# aka iterServices in Python
|
|
125
|
+
def Yadis::each_service(xrds_tree, &block)
|
|
126
|
+
xrd = get_yadis_xrd(xrds_tree)
|
|
127
|
+
xrd.each_element('Service', &block)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def Yadis::services(xrds_tree)
|
|
131
|
+
s = []
|
|
132
|
+
each_service(xrds_tree) { |service|
|
|
133
|
+
s << service
|
|
134
|
+
}
|
|
135
|
+
return s
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def Yadis::expand_service(service_element)
|
|
139
|
+
es = service_element.elements
|
|
140
|
+
uris = es.each('URI') { |u| }
|
|
141
|
+
uris = prio_sort(uris)
|
|
142
|
+
types = es.each('Type/text()')
|
|
143
|
+
# REXML::Text objects are not strings.
|
|
144
|
+
types = types.collect { |t| t.to_s }
|
|
145
|
+
uris.collect { |uri| [types, uri.text, service_element] }
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Sort a list of elements that have priority attributes.
|
|
149
|
+
def Yadis::prio_sort(elements)
|
|
150
|
+
elements.sort { |a,b|
|
|
151
|
+
a.attribute('priority').to_s.to_i <=> b.attribute('priority').to_s.to_i
|
|
152
|
+
}
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require 'openid/yadis/xrds'
|
|
2
|
+
require 'openid/fetchers'
|
|
3
|
+
|
|
4
|
+
module OpenID
|
|
5
|
+
module Yadis
|
|
6
|
+
module XRI
|
|
7
|
+
|
|
8
|
+
# The '(' is for cross-reference authorities, and hopefully has a
|
|
9
|
+
# matching ')' somewhere.
|
|
10
|
+
XRI_AUTHORITIES = ["!", "=", "@", "+", "$", "("]
|
|
11
|
+
|
|
12
|
+
def self.identifier_scheme(identifier)
|
|
13
|
+
if (!identifier.nil? and
|
|
14
|
+
identifier.length > 0 and
|
|
15
|
+
(identifier.match('^xri://') or
|
|
16
|
+
XRI_AUTHORITIES.member?(identifier[0].chr)))
|
|
17
|
+
return :xri
|
|
18
|
+
else
|
|
19
|
+
return :uri
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Transform an XRI reference to an IRI reference. Note this is
|
|
24
|
+
# not not idempotent, so do not apply this to an identifier more
|
|
25
|
+
# than once. XRI Syntax section 2.3.1
|
|
26
|
+
def self.to_iri_normal(xri)
|
|
27
|
+
iri = xri.dup
|
|
28
|
+
iri.insert(0, 'xri://') if not iri.match('^xri://')
|
|
29
|
+
return escape_for_iri(iri)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Note this is not not idempotent, so do not apply this more than
|
|
33
|
+
# once. XRI Syntax section 2.3.2
|
|
34
|
+
def self.escape_for_iri(xri)
|
|
35
|
+
esc = xri.dup
|
|
36
|
+
# encode all %
|
|
37
|
+
esc.gsub!(/%/, '%25')
|
|
38
|
+
esc.gsub!(/\((.*?)\)/) { |xref_match|
|
|
39
|
+
xref_match.gsub(/[\/\?\#]/) { |char_match|
|
|
40
|
+
CGI::escape(char_match)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return esc
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Transform an XRI reference to a URI reference. Note this is not
|
|
47
|
+
# not idempotent, so do not apply this to an identifier more than
|
|
48
|
+
# once. XRI Syntax section 2.3.1
|
|
49
|
+
def self.to_uri_normal(xri)
|
|
50
|
+
return iri_to_uri(to_iri_normal(xri))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# RFC 3987 section 3.1
|
|
54
|
+
def self.iri_to_uri(iri)
|
|
55
|
+
uri = iri.dup
|
|
56
|
+
# for char in ucschar or iprivate
|
|
57
|
+
# convert each char to %HH%HH%HH (as many %HH as octets)
|
|
58
|
+
return uri
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.provider_is_authoritative(provider_id, canonical_id)
|
|
62
|
+
lastbang = canonical_id.rindex('!')
|
|
63
|
+
return false unless lastbang
|
|
64
|
+
parent = canonical_id[0...lastbang]
|
|
65
|
+
return parent == provider_id
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.root_authority(xri)
|
|
69
|
+
xri = xri[6..-1] if xri.index('xri://') == 0
|
|
70
|
+
authority = xri.split('/', 2)[0]
|
|
71
|
+
if authority[0].chr == '('
|
|
72
|
+
root = authority[0...authority.index(')')+1]
|
|
73
|
+
elsif XRI_AUTHORITIES.member?(authority[0].chr)
|
|
74
|
+
root = authority[0].chr
|
|
75
|
+
else
|
|
76
|
+
root = authority.split(/[!*]/)[0]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
self.make_xri(root)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def self.make_xri(xri)
|
|
83
|
+
if xri.index('xri://') != 0
|
|
84
|
+
xri = 'xri://' + xri
|
|
85
|
+
end
|
|
86
|
+
return xri
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
require "cgi"
|
|
2
|
+
require "openid/yadis/xri"
|
|
3
|
+
require "openid/yadis/xrds"
|
|
4
|
+
require "openid/fetchers"
|
|
5
|
+
|
|
6
|
+
module OpenID
|
|
7
|
+
|
|
8
|
+
module Yadis
|
|
9
|
+
|
|
10
|
+
module XRI
|
|
11
|
+
|
|
12
|
+
class XRIHTTPError < StandardError; end
|
|
13
|
+
|
|
14
|
+
class ProxyResolver
|
|
15
|
+
|
|
16
|
+
DEFAULT_PROXY = 'http://proxy.xri.net/'
|
|
17
|
+
|
|
18
|
+
def initialize(proxy_url=nil)
|
|
19
|
+
if proxy_url
|
|
20
|
+
@proxy_url = proxy_url
|
|
21
|
+
else
|
|
22
|
+
@proxy_url = DEFAULT_PROXY
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
@proxy_url += '/' unless @proxy_url.match('/$')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def query_url(xri, service_type=nil)
|
|
29
|
+
# URI normal form has a leading xri://, but we need to strip
|
|
30
|
+
# that off again for the QXRI. This is under discussion for
|
|
31
|
+
# XRI Resolution WD 11.
|
|
32
|
+
qxri = XRI.to_uri_normal(xri)[6..-1]
|
|
33
|
+
hxri = @proxy_url + qxri
|
|
34
|
+
args = {'_xrd_r' => 'application/xrds+xml'}
|
|
35
|
+
if service_type
|
|
36
|
+
args['_xrd_t'] = service_type
|
|
37
|
+
else
|
|
38
|
+
# don't perform service endpoint selection
|
|
39
|
+
args['_xrd_r'] += ';sep=false'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
return XRI.append_args(hxri, args)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def query(xri, service_types)
|
|
46
|
+
# these can be query args or http headers, needn't be both.
|
|
47
|
+
# headers = {'Accept' => 'application/xrds+xml;sep=true'}
|
|
48
|
+
canonicalID = nil
|
|
49
|
+
|
|
50
|
+
services = service_types.collect { |service_type|
|
|
51
|
+
url = self.query_url(xri, service_type)
|
|
52
|
+
begin
|
|
53
|
+
response = OpenID.fetch(url)
|
|
54
|
+
rescue
|
|
55
|
+
raise XRIHTTPError, ["Could not fetch #{xri}", $!]
|
|
56
|
+
end
|
|
57
|
+
raise XRIHTTPError, "Could not fetch #{xri}" if response.nil?
|
|
58
|
+
|
|
59
|
+
xrds = Yadis::parseXRDS(response.body)
|
|
60
|
+
canonicalID = Yadis::get_canonical_id(xri, xrds)
|
|
61
|
+
|
|
62
|
+
Yadis::services(xrds) unless xrds.nil?
|
|
63
|
+
}
|
|
64
|
+
# TODO:
|
|
65
|
+
# * If we do get hits for multiple service_types, we're almost
|
|
66
|
+
# certainly going to have duplicated service entries and
|
|
67
|
+
# broken priority ordering.
|
|
68
|
+
services = services.inject([]) { |flatter, some_services|
|
|
69
|
+
flatter += some_services unless some_services.nil?
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return canonicalID, services
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self.urlencode(args)
|
|
77
|
+
a = []
|
|
78
|
+
args.each do |key, val|
|
|
79
|
+
a << (CGI::escape(key) + "=" + CGI::escape(val))
|
|
80
|
+
end
|
|
81
|
+
a.join("&")
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def self.append_args(url, args)
|
|
85
|
+
return url if args.length == 0
|
|
86
|
+
|
|
87
|
+
# rstrip question marks
|
|
88
|
+
rstripped = url.dup
|
|
89
|
+
while rstripped[-1].chr == '?'
|
|
90
|
+
rstripped = rstripped[0...rstripped.length-1]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
if rstripped.index('?')
|
|
94
|
+
sep = '&'
|
|
95
|
+
else
|
|
96
|
+
sep = '?'
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
return url + sep + XRI.urlencode(args)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end
|
data/lib/openid.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright 2006-2007 JanRain, Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
|
4
|
+
# may not use this file except in compliance with the License. You may
|
|
5
|
+
# obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
12
|
+
# implied. See the License for the specific language governing
|
|
13
|
+
# permissions and limitations under the License.
|
|
14
|
+
|
|
15
|
+
module OpenID
|
|
16
|
+
VERSION = "2.1.8"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
require "openid/consumer"
|
|
20
|
+
require 'openid/server'
|