ruby-yadis 0.3 → 0.3.1
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/lib/yadis/xrds.rb +15 -14
- data/test/data/brianellin.mylid.xrds +42 -0
- data/test/data/proxy-june1.xrds +31 -0
- data/test/data/weirdver.xrds +15 -0
- data/test/test_xrds.rb +22 -0
- metadata +8 -11
- data/lib/yadis.rb~ +0 -1
- data/lib/yadis/fetcher.rb~ +0 -79
- data/lib/yadis/manager.rb~ +0 -138
- data/lib/yadis/service.rb~ +0 -24
- data/lib/yadis/xrds.rb~ +0 -128
- data/lib/yadis/yadis.rb~ +0 -104
data/lib/yadis/xrds.rb
CHANGED
@@ -4,13 +4,15 @@ require 'yadis/service'
|
|
4
4
|
# Class that handles XRDS parsing and XRD Service element extraction.
|
5
5
|
|
6
6
|
module XRDSUtil
|
7
|
-
|
8
|
-
@@
|
9
|
-
|
7
|
+
|
8
|
+
@@namespaces = {
|
9
|
+
'xrdsns' => 'xri://$xrds',
|
10
|
+
'xrdns' => 'xri://$xrd*($v*2.0)'
|
11
|
+
}
|
10
12
|
|
11
13
|
def last_xrd(root_element)
|
12
|
-
REXML::XPath.match(root_element, '/
|
13
|
-
@@
|
14
|
+
REXML::XPath.match(root_element, '/xrdsns:XRDS/xrdns:XRD',
|
15
|
+
@@namespaces)[-1]
|
14
16
|
end
|
15
17
|
|
16
18
|
end
|
@@ -22,7 +24,7 @@ class XRDS
|
|
22
24
|
|
23
25
|
# Method for producing a valid XRDS object. Accepts an XML
|
24
26
|
# String. Returns an XRDS object on success, or nil on failure.
|
25
|
-
# Same as calling XRDS.new, but does not
|
27
|
+
# Same as calling XRDS.new, but does not raise ArgumentErrors.
|
26
28
|
def XRDS.parse(xml)
|
27
29
|
begin
|
28
30
|
return new(xml)
|
@@ -56,17 +58,14 @@ class XRDS
|
|
56
58
|
if xml.root.nil?
|
57
59
|
raise ArgumentError, "No document root"
|
58
60
|
end
|
59
|
-
|
60
|
-
xmlns = xml.root.attributes['xmlns']
|
61
|
-
if xmlns != @@default_namespace
|
62
|
-
raise ArgumentError, "Unknown XRID version #{xmlns.to_s}"
|
63
|
-
end
|
64
61
|
|
65
62
|
xrd = self.last_xrd(xml.root)
|
66
63
|
raise ArgumentError, "No XRD Elements found" if xrd.nil?
|
67
64
|
|
68
|
-
@services = {} # keyed by [service_priority, uri_priority]
|
69
|
-
|
65
|
+
@services = {} # keyed by [service_priority, uri_priority]
|
66
|
+
REXML::XPath.each(xrd, 'xrdns:Service', @@namespaces) do |s|
|
67
|
+
_create_services(s)
|
68
|
+
end
|
70
69
|
end
|
71
70
|
|
72
71
|
|
@@ -98,7 +97,9 @@ class XRDS
|
|
98
97
|
service.service_types = []
|
99
98
|
|
100
99
|
service_element.elements.each('Type') do |t|
|
101
|
-
|
100
|
+
# XXX: If the Type element is empty, should we add an empty element
|
101
|
+
# to our list, or none at all?
|
102
|
+
service.service_types << t.text.strip unless t.text.nil?
|
102
103
|
end
|
103
104
|
|
104
105
|
sp = service_element.attributes['priority']
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<XRDS xmlns="xri://$xrds" xmlns:xrd="xri://$xrd*($v*2.0)">
|
3
|
+
<xrd:XRD>
|
4
|
+
<xrd:Service priority="1">
|
5
|
+
<xrd:Type>http://lid.netmesh.org/minimum-lid/2.0b9</xrd:Type>
|
6
|
+
<xrd:URI>http://mylid.net/brianellin</xrd:URI>
|
7
|
+
</xrd:Service>
|
8
|
+
<xrd:Service priority="2">
|
9
|
+
<xrd:Type>http://lid.netmesh.org/sso/2.0b9</xrd:Type>
|
10
|
+
<xrd:URI>http://mylid.net/brianellin</xrd:URI>
|
11
|
+
</xrd:Service>
|
12
|
+
<xrd:Service priority="3">
|
13
|
+
<xrd:Type>http://lid.netmesh.org/sso/1.0</xrd:Type>
|
14
|
+
<xrd:URI>http://mylid.net/brianellin</xrd:URI>
|
15
|
+
</xrd:Service>
|
16
|
+
<xrd:Service priority="4">
|
17
|
+
<xrd:Type>http://lid.netmesh.org/relying-party/2.0b9</xrd:Type>
|
18
|
+
<xrd:URI>http://mylid.net/brianellin</xrd:URI>
|
19
|
+
</xrd:Service>
|
20
|
+
<xrd:Service priority="5">
|
21
|
+
<xrd:Type>http://lid.netmesh.org/traversal/2.0b9</xrd:Type>
|
22
|
+
<xrd:URI>http://mylid.net/brianellin</xrd:URI>
|
23
|
+
</xrd:Service>
|
24
|
+
<xrd:Service priority="6">
|
25
|
+
<xrd:Type>http://lid.netmesh.org/format-negotiation/2.0b9</xrd:Type>
|
26
|
+
<xrd:URI>http://mylid.net/brianellin</xrd:URI>
|
27
|
+
</xrd:Service>
|
28
|
+
<xrd:Service priority="7">
|
29
|
+
<xrd:Type>http://lid.netmesh.org/post/sender/2.0b9</xrd:Type>
|
30
|
+
<xrd:URI>http://mylid.net/brianellin</xrd:URI>
|
31
|
+
</xrd:Service>
|
32
|
+
<xrd:Service priority="8">
|
33
|
+
<xrd:Type>http://lid.netmesh.org/post/receiver/2.0b9</xrd:Type>
|
34
|
+
<xrd:URI>http://mylid.net/brianellin</xrd:URI>
|
35
|
+
</xrd:Service>
|
36
|
+
<xrd:Service priority="9">
|
37
|
+
<xrd:Type>http://openid.net/signon/1.0</xrd:Type>
|
38
|
+
<xrd:URI>http://mylid.net/brianellin</xrd:URI>
|
39
|
+
<openid:Delegate xmlns:openid="http://openid.net/xmlns/1.0">http://mylid.net/brianellin</openid:Delegate>
|
40
|
+
</xrd:Service>
|
41
|
+
</xrd:XRD>
|
42
|
+
</XRDS>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<XRDS ref="xri://=keturn" xmlns="xri://$xrds">
|
3
|
+
<XRD xmlns="xri://$xrd*($v*2.0)">
|
4
|
+
<Query>*keturn</Query>
|
5
|
+
<Status code="100"/>
|
6
|
+
<Expires>2006-06-01T18:00:49.000Z</Expires>
|
7
|
+
<ProviderID>xri://=</ProviderID>
|
8
|
+
<LocalID priority="10">!2397.58EC.8F7D.D097</LocalID>
|
9
|
+
<CanonicalID priority="10">=!2397.58EC.8F7D.D097</CanonicalID>
|
10
|
+
<Service priority="10">
|
11
|
+
<Type/>
|
12
|
+
<Type>xri://+i-service*(+forwarding)*($v*1.0)</Type>
|
13
|
+
<ProviderID>xri://!!1003</ProviderID>
|
14
|
+
<URI priority="10">https://forwarding.godaddy.amsoftsystems.com</URI>
|
15
|
+
</Service>
|
16
|
+
<Service priority="10">
|
17
|
+
<Type>xri://+i-service*(+contact)*($v*1.0)</Type>
|
18
|
+
<ProviderID>xri://!!1003</ProviderID>
|
19
|
+
<Path>+contact</Path>
|
20
|
+
<MediaType/>
|
21
|
+
<MediaType>text/html</MediaType>
|
22
|
+
<URI priority="10">https://contact.godaddy.amsoftsystems.com</URI>
|
23
|
+
</Service>
|
24
|
+
<Service priority="10">
|
25
|
+
<Type>xri://+i-service*(+authn)*(+saml)*($v*1.0)</Type>
|
26
|
+
<ProviderID>xri://!!1003</ProviderID>
|
27
|
+
<Path>+login</Path>
|
28
|
+
<URI priority="10">https://isso.godaddy.amsoftsystems.com</URI>
|
29
|
+
</Service>
|
30
|
+
</XRD>
|
31
|
+
</XRDS>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<xrds:XRDS
|
3
|
+
xmlns:xrds="xri://$xrds"
|
4
|
+
xmlns:openid="http://openid.net/xmlns/1.0"
|
5
|
+
xmlns="xri://$xrd*($v*1.14121)">
|
6
|
+
<XRD>
|
7
|
+
|
8
|
+
<Service priority="0">
|
9
|
+
<Type>http://openid.net/signon/1.0</Type>
|
10
|
+
<URI>http://www.myopenid.com/server</URI>
|
11
|
+
<openid:Delegate>http://brian.myopenid.com/</openid:Delegate>
|
12
|
+
</Service>
|
13
|
+
|
14
|
+
</XRD>
|
15
|
+
</xrds:XRDS>
|
data/test/test_xrds.rb
CHANGED
@@ -9,6 +9,12 @@ class XRDSTestCase < Test::Unit::TestCase
|
|
9
9
|
assert_not_nil(xrds)
|
10
10
|
assert_equal(xrds.services.length, 1)
|
11
11
|
end
|
12
|
+
|
13
|
+
File.open('data/brianellin.mylid.xrds') do |f|
|
14
|
+
xrds = XRDS.new(f.read)
|
15
|
+
assert_not_nil(xrds)
|
16
|
+
assert_equal(xrds.services.length, 9)
|
17
|
+
end
|
12
18
|
end
|
13
19
|
|
14
20
|
def test_xrds_good_multi
|
@@ -29,6 +35,22 @@ class XRDSTestCase < Test::Unit::TestCase
|
|
29
35
|
end
|
30
36
|
end
|
31
37
|
|
38
|
+
# This is like brian.multi, but uses namespaces a little differently.
|
39
|
+
def test_xrds_good_namespaces
|
40
|
+
File.open('data/proxy-june1.xrds') do |f|
|
41
|
+
xrds = XRDS.new(f.read)
|
42
|
+
assert_not_nil(xrds)
|
43
|
+
assert_equal(3, xrds.services.length)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_xrds_unknown_xrd_version
|
48
|
+
File.open('data/weirdver.xrds') do |f|
|
49
|
+
xrds = XRDS.parse(f.read)
|
50
|
+
assert_nil(xrds)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
32
54
|
def test_xrds_bad
|
33
55
|
assert_nil(XRDS.parse(nil))
|
34
56
|
assert_nil(XRDS.parse(5))
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-yadis
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version:
|
7
|
-
date: 2006-
|
6
|
+
version: 0.3.1
|
7
|
+
date: 2006-06-09 00:00:00 -07:00
|
8
8
|
summary: A library for performing Yadis service discovery
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -31,19 +31,13 @@ files:
|
|
31
31
|
- examples/openid.rb
|
32
32
|
- lib/yadis.rb
|
33
33
|
- lib/yadis
|
34
|
-
- lib/yadis.rb~
|
35
34
|
- lib/yadis/parsehtml.rb
|
36
35
|
- lib/yadis/xrds.rb
|
37
36
|
- lib/yadis/yadis.rb
|
38
37
|
- lib/yadis/fetcher.rb
|
39
38
|
- lib/yadis/htmltokenizer.rb
|
40
39
|
- lib/yadis/manager.rb
|
41
|
-
- lib/yadis/yadis.rb~
|
42
40
|
- lib/yadis/service.rb
|
43
|
-
- lib/yadis/manager.rb~
|
44
|
-
- lib/yadis/service.rb~
|
45
|
-
- lib/yadis/xrds.rb~
|
46
|
-
- lib/yadis/fetcher.rb~
|
47
41
|
- test/test_parse.rb
|
48
42
|
- test/data
|
49
43
|
- test/test_discovery.rb
|
@@ -52,12 +46,15 @@ files:
|
|
52
46
|
- test/runtests.rb
|
53
47
|
- test/data/manifest.txt
|
54
48
|
- test/data/brian.xrds
|
55
|
-
- test/data/index.html
|
56
|
-
- test/data/brian.multi.xrds
|
57
49
|
- test/data/brian_priority.xrds
|
50
|
+
- test/data/brian.multi.xrds
|
51
|
+
- test/data/index.html
|
58
52
|
- test/data/brian.multi_uri.xrds
|
59
|
-
- test/data/index_xrds.html
|
60
53
|
- test/data/index_yadis.html
|
54
|
+
- test/data/index_xrds.html
|
55
|
+
- test/data/proxy-june1.xrds
|
56
|
+
- test/data/weirdver.xrds
|
57
|
+
- test/data/brianellin.mylid.xrds
|
61
58
|
- README
|
62
59
|
- INSTALL
|
63
60
|
- COPYING
|
data/lib/yadis.rb~
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'yadis/yadis'
|
data/lib/yadis/fetcher.rb~
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
require "uri"
|
2
|
-
|
3
|
-
begin
|
4
|
-
require "net/https"
|
5
|
-
rescue LoadError
|
6
|
-
HAS_OPENSSL_ = false
|
7
|
-
require 'net/http'
|
8
|
-
else
|
9
|
-
HAS_OPENSSL_ = true
|
10
|
-
end
|
11
|
-
|
12
|
-
class NetHTTPFetcher
|
13
|
-
|
14
|
-
attr_accessor :ca_path
|
15
|
-
|
16
|
-
def initialize(read_timeout=20, open_timeout=20)
|
17
|
-
@read_timeout = read_timeout
|
18
|
-
@open_timeout = open_timeout
|
19
|
-
@ca_path = nil
|
20
|
-
end
|
21
|
-
|
22
|
-
def get(url, params = nil)
|
23
|
-
resp, final_url = do_get(url, params)
|
24
|
-
if resp.nil?
|
25
|
-
nil
|
26
|
-
else
|
27
|
-
[final_url, resp]
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
protected
|
32
|
-
|
33
|
-
# return a Net::HTTP object ready for use
|
34
|
-
def get_http_obj(uri)
|
35
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
36
|
-
http.read_timeout = @read_timeout
|
37
|
-
http.open_timeout = @open_timeout
|
38
|
-
|
39
|
-
if uri.scheme == 'https'
|
40
|
-
if HAS_OPENSSL_
|
41
|
-
http.use_ssl = true
|
42
|
-
if @ca_path
|
43
|
-
http.ca_file = @ca_path
|
44
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
45
|
-
else
|
46
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
47
|
-
STDERR.puts("Warning: fetching over https without verifying server certificate")
|
48
|
-
end
|
49
|
-
else
|
50
|
-
STDERR.puts('Warning: trying to fetch HTTPS URL without OpenSSL support')
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
return http
|
55
|
-
end
|
56
|
-
|
57
|
-
# do a GET following redirects limit deep
|
58
|
-
def do_get(url, params, limit=5)
|
59
|
-
if limit == 0
|
60
|
-
return nil
|
61
|
-
end
|
62
|
-
begin
|
63
|
-
uri = URI.parse(url)
|
64
|
-
http = get_http_obj(uri)
|
65
|
-
resp = http.request_get(uri.request_uri, params)
|
66
|
-
rescue
|
67
|
-
nil
|
68
|
-
else
|
69
|
-
case resp
|
70
|
-
when Net::HTTPSuccess then [resp, URI.parse(url).to_s]
|
71
|
-
when Net::HTTPRedirection then do_get(resp["location"], params, limit-1)
|
72
|
-
else
|
73
|
-
STDERR.puts("ERROR, what to do with #{resp}")
|
74
|
-
nil
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
data/lib/yadis/manager.rb~
DELETED
@@ -1,138 +0,0 @@
|
|
1
|
-
require 'yadis/yadis'
|
2
|
-
|
3
|
-
class YadisServiceManager
|
4
|
-
|
5
|
-
attr_reader :starting_url, :yadis_url, :services, :session_key, :current
|
6
|
-
|
7
|
-
def initialize(starting_url, yadis_url, services)
|
8
|
-
@starting_url = starting_url
|
9
|
-
@yadis_url = yadis_url
|
10
|
-
@services = services
|
11
|
-
@current = nil
|
12
|
-
end
|
13
|
-
|
14
|
-
def next
|
15
|
-
@current = @services.shift
|
16
|
-
end
|
17
|
-
|
18
|
-
def for_url?(url)
|
19
|
-
url == @starting_url or url == @yadis_url
|
20
|
-
end
|
21
|
-
|
22
|
-
def started?
|
23
|
-
not @current.nil?
|
24
|
-
end
|
25
|
-
|
26
|
-
def length
|
27
|
-
@services.length
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
|
32
|
-
class Discovery
|
33
|
-
|
34
|
-
@@default_suffix = nil
|
35
|
-
@@prefix = '_yadis_services_'
|
36
|
-
|
37
|
-
def initialize(session, url, session_key_siffix=nil)
|
38
|
-
@session = session
|
39
|
-
@url = url
|
40
|
-
@session_key = @@prefix + (session_key_suffix or @@default_suffix)
|
41
|
-
end
|
42
|
-
|
43
|
-
def next_service(discover_block)
|
44
|
-
manager = self.get_manager
|
45
|
-
if manager and manager.length <= 0
|
46
|
-
self.destroy_manager
|
47
|
-
manager = nil
|
48
|
-
end
|
49
|
-
|
50
|
-
unless manager
|
51
|
-
begin
|
52
|
-
yadis_url, services = self.discover
|
53
|
-
rescue YADISParseError, YADISHTTPError
|
54
|
-
manager = nil
|
55
|
-
else
|
56
|
-
manager = self.create_manager(services, yadis_url)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
if manager
|
61
|
-
service = manager.next
|
62
|
-
self.store_manager(manager)
|
63
|
-
else
|
64
|
-
service = nil
|
65
|
-
end
|
66
|
-
|
67
|
-
return service
|
68
|
-
end
|
69
|
-
|
70
|
-
def finish
|
71
|
-
manager = self.get_manager
|
72
|
-
return nil unless manager
|
73
|
-
|
74
|
-
service = manager.current
|
75
|
-
self.destroy_manager
|
76
|
-
return service
|
77
|
-
end
|
78
|
-
|
79
|
-
def get_manager
|
80
|
-
manager = @session[@session_key]
|
81
|
-
|
82
|
-
# make sure we've got the right manager here
|
83
|
-
if manager and manager.for_url?(@url)
|
84
|
-
return manager
|
85
|
-
end
|
86
|
-
|
87
|
-
return nil
|
88
|
-
end
|
89
|
-
|
90
|
-
def create_manager(services, yadis_url=nil)
|
91
|
-
if self.get_manager
|
92
|
-
raise ArgumentError, "There is already a manager for #{@url}"
|
93
|
-
end
|
94
|
-
|
95
|
-
if services.length > 0
|
96
|
-
manager = YadisServiceManager.new(@url, yadis_url, services)
|
97
|
-
self.store_manager(manager)
|
98
|
-
else
|
99
|
-
manager = nil
|
100
|
-
end
|
101
|
-
|
102
|
-
return manager
|
103
|
-
end
|
104
|
-
|
105
|
-
def destroy_manager
|
106
|
-
if self.get_manager
|
107
|
-
begin
|
108
|
-
@session.delete(@session_key)
|
109
|
-
rescue
|
110
|
-
# sometimes Hash like session objects don't have a delete
|
111
|
-
# method. We handle that case by assigning nil to the session[key]
|
112
|
-
@session[@session_key] = nil
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def store_manager(manager)
|
118
|
-
@session[@session_key] = manager
|
119
|
-
end
|
120
|
-
|
121
|
-
# The filter argument is a Proc that will be used to call
|
122
|
-
# YADIS.filter_services. See the documentation for YADIS.filter_services
|
123
|
-
# for more information about writing filters.
|
124
|
-
def discover(filter=nil)
|
125
|
-
y = YADIS.new(@url)
|
126
|
-
|
127
|
-
# a default filter which sends through everything. you should
|
128
|
-
# probably consider writing a custom filter and passing it in.
|
129
|
-
unless filter
|
130
|
-
filter = lambda {|s| s}
|
131
|
-
end
|
132
|
-
|
133
|
-
return [y.url, y.filter_services(filter)]
|
134
|
-
end
|
135
|
-
|
136
|
-
end
|
137
|
-
|
138
|
-
|
data/lib/yadis/service.rb~
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'rexml/document'
|
2
|
-
|
3
|
-
# Class representing an XRD Service element.
|
4
|
-
class ServiceEndpoint
|
5
|
-
|
6
|
-
attr_accessor :service_types, :uri, :yadis_uri, :element, :yadis
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@service_types = []
|
10
|
-
@uri = nil
|
11
|
-
@yadis_uri = nil
|
12
|
-
@element = nil
|
13
|
-
@yadis_uri = nil
|
14
|
-
end
|
15
|
-
|
16
|
-
def match_type_uris(type_uris)
|
17
|
-
type_uris.find_all {|t| @service_types.member?(t)}
|
18
|
-
end
|
19
|
-
|
20
|
-
def ==(other)
|
21
|
-
return self.instance_variables == other.instance_variables
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
data/lib/yadis/xrds.rb~
DELETED
@@ -1,128 +0,0 @@
|
|
1
|
-
require 'rexml/document'
|
2
|
-
require 'yadis/service'
|
3
|
-
|
4
|
-
# Class that handles XRDS parsing and XRD Service element extraction.
|
5
|
-
|
6
|
-
module XRDSUtil
|
7
|
-
|
8
|
-
@@default_namespace = 'xri://$xrd*($v*2.0)'
|
9
|
-
@@xrds_namespace = {'xrds' => 'xri://$xrds'}
|
10
|
-
|
11
|
-
def last_xrd(root_element)
|
12
|
-
REXML::XPath.match(root_element, '/xrds:XRDS/XRD',
|
13
|
-
@@xrds_namespace)[-1]
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
class XRDS
|
19
|
-
|
20
|
-
include XRDSUtil
|
21
|
-
attr_reader :xml
|
22
|
-
|
23
|
-
# Method for producing a valid XRDS object. Accepts an XML
|
24
|
-
# String. Returns an XRDS object on success, or nil on failure.
|
25
|
-
# Same as calling XRDS.new, but does not rails ArgumentErrors.
|
26
|
-
def XRDS.parse(xml)
|
27
|
-
begin
|
28
|
-
return new(xml)
|
29
|
-
rescue
|
30
|
-
return nil
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# Create a new XRDS object. Raises ArgumentError if xml_text is
|
35
|
-
# malformed or invalid XRDS.
|
36
|
-
def initialize(xml_text)
|
37
|
-
parse_xml(xml_text)
|
38
|
-
end
|
39
|
-
|
40
|
-
def parse_xml(xml_text)
|
41
|
-
begin
|
42
|
-
xml = @xml = REXML::Document.new(xml_text)
|
43
|
-
rescue
|
44
|
-
raise ArgumentError, "Can't parse XRDS"
|
45
|
-
end
|
46
|
-
|
47
|
-
if xml.root.nil?
|
48
|
-
raise ArgumentError, "No document root"
|
49
|
-
end
|
50
|
-
|
51
|
-
xmlns = xml.root.attributes['xmlns']
|
52
|
-
if xmlns != @@default_namespace
|
53
|
-
raise ArgumentError, "Unknown XRID version #{xmlns.to_s}"
|
54
|
-
end
|
55
|
-
|
56
|
-
xrd = self.last_xrd(xml.root)
|
57
|
-
raise ArgumentError, "No XRD Elements found" if xrd.nil?
|
58
|
-
|
59
|
-
@services = {} # keyed by [service_priority, uri_priority]
|
60
|
-
xrd.elements.each('Service') {|s| _create_services(s)}
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
# Returns an Array of ServiceEndpoint objects, sorted by priority. Highest
|
65
|
-
# priority is at element 0.
|
66
|
-
def services
|
67
|
-
s = []
|
68
|
-
|
69
|
-
@services.keys.sort.each do |key|
|
70
|
-
services_list = @services[key].dup
|
71
|
-
|
72
|
-
# randomize services with the same priority
|
73
|
-
while services_list.length > 0
|
74
|
-
s << services_list.delete_at((rand * services_list.length).to_i)
|
75
|
-
end
|
76
|
-
|
77
|
-
end
|
78
|
-
|
79
|
-
return s
|
80
|
-
end
|
81
|
-
|
82
|
-
private
|
83
|
-
|
84
|
-
# create services objects
|
85
|
-
def _create_services(service_element)
|
86
|
-
service = ServiceEndpoint.new
|
87
|
-
service.element = service_element
|
88
|
-
service.uri = nil
|
89
|
-
service.service_types = []
|
90
|
-
|
91
|
-
service_element.elements.each('Type') do |t|
|
92
|
-
service.service_types << t.text.strip
|
93
|
-
end
|
94
|
-
|
95
|
-
sp = service_element.attributes['priority']
|
96
|
-
service_priority = sp ? sp.to_i : -1
|
97
|
-
|
98
|
-
if service.element.elements['URI']
|
99
|
-
service.element.elements.each('URI') do |uri|
|
100
|
-
_service = service.dup
|
101
|
-
_service.uri = uri.text.strip
|
102
|
-
|
103
|
-
up = uri.attributes['priority']
|
104
|
-
uri_priority = up ? up.to_i : -1
|
105
|
-
priority = [service_priority, uri_priority]
|
106
|
-
|
107
|
-
_add_service(priority, _service)
|
108
|
-
end
|
109
|
-
|
110
|
-
else
|
111
|
-
priority = [service_priority, -1]
|
112
|
-
_add_service(priority, service)
|
113
|
-
|
114
|
-
end
|
115
|
-
|
116
|
-
end
|
117
|
-
|
118
|
-
def _add_service(priority, service)
|
119
|
-
unless @services.has_key?(priority)
|
120
|
-
@services[priority] = []
|
121
|
-
end
|
122
|
-
|
123
|
-
# services with the same priority are appended to the list
|
124
|
-
@services[priority] << service
|
125
|
-
end
|
126
|
-
|
127
|
-
end
|
128
|
-
|
data/lib/yadis/yadis.rb~
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
require 'yadis/xrds'
|
2
|
-
require 'yadis/fetcher'
|
3
|
-
require 'yadis/parsehtml'
|
4
|
-
|
5
|
-
class YADISParseError < StandardError; end
|
6
|
-
class YADISHTTPError < StandardError; end
|
7
|
-
|
8
|
-
class YADIS
|
9
|
-
|
10
|
-
@@ca_path = nil
|
11
|
-
attr_accessor :uri, :xrds_uri, :xrds
|
12
|
-
|
13
|
-
# Discover services for a given URI. Please note that no normalization
|
14
|
-
# will be done to the passed in URI, it should be a textually
|
15
|
-
# valid URI string before calling discover.
|
16
|
-
#
|
17
|
-
# Returns nil if no XRDS was found, or a YADIS object on success. This
|
18
|
-
# method is essentially the same as YADIS.new, but does not raise any
|
19
|
-
# exceptions.
|
20
|
-
def YADIS.discover(uri)
|
21
|
-
return nil unless uri
|
22
|
-
begin
|
23
|
-
return YADIS.new(uri)
|
24
|
-
rescue
|
25
|
-
return nil
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# Set the path to a certificate authority pem file, for verifying
|
30
|
-
# server certificates of HTTPS pages. If you are interested in verifying
|
31
|
-
# certs like the mozilla web browser, have a look at the files here:
|
32
|
-
#
|
33
|
-
# http://curl.haxx.se/docs/caextract.html
|
34
|
-
def YADIS.ca_path=(ca_path)
|
35
|
-
ca_path = ca_path.to_s
|
36
|
-
if File.exists?(ca_path)
|
37
|
-
@@ca_path = ca_path
|
38
|
-
else
|
39
|
-
raise ArgumentError, "#{ca_path} is not a valid file path"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# Discover services for a URI using the Yadis protocol. +uri+ should
|
44
|
-
# be a valid URI represented as a string. This method may raise
|
45
|
-
# YADISParseError in the case of an invalid or unparsable XRDS file,
|
46
|
-
# or YADISHTTPError is the URI cannot be fetched.
|
47
|
-
def initialize(uri)
|
48
|
-
http = NetHTTPFetcher.new
|
49
|
-
http.ca_path = @@ca_path if @@ca_path
|
50
|
-
headers = {'Accept' => 'application/xrds+xml'}
|
51
|
-
|
52
|
-
response = http.get(uri, headers)
|
53
|
-
raise YADISHTTPError, "Could not fetch #{uri}" if response.nil?
|
54
|
-
|
55
|
-
uri, resp_payload = response
|
56
|
-
xrds_uri = uri
|
57
|
-
|
58
|
-
header = resp_payload['x-xrds-location']
|
59
|
-
header = resp_payload['x-yadis-location'] if header.nil?
|
60
|
-
|
61
|
-
if header
|
62
|
-
xrds_uri = header
|
63
|
-
response = http.get(xrds_uri)
|
64
|
-
raise YADISHTTPError, "Could not fetch XRDS #{xrds_uri}" if response.nil?
|
65
|
-
resp_payload = response[1]
|
66
|
-
end
|
67
|
-
|
68
|
-
unless resp_payload['content-type'] == 'application/xrds+xml'
|
69
|
-
loc = html_yadis_location(resp_payload.body)
|
70
|
-
unless loc.nil?
|
71
|
-
xrds_uri, resp_payload = http.get(loc)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
xrds = XRDS.parse(resp_payload.body)
|
76
|
-
raise YADISParseError, "Bad XRDS" if xrds.nil?
|
77
|
-
|
78
|
-
@uri = uri
|
79
|
-
@xrds_uri = xrds_uri
|
80
|
-
@xrds = xrds
|
81
|
-
end
|
82
|
-
|
83
|
-
# Returns an Array Service objects sorted by priority.
|
84
|
-
def services
|
85
|
-
@xrds.services.each {|s| s.yadis = self}
|
86
|
-
@xrds.services
|
87
|
-
end
|
88
|
-
|
89
|
-
# Returns a list of services, ordered by priority,
|
90
|
-
# that match the filter. filter is a Proc object that produces
|
91
|
-
# ServiceEnpoint objects, subclasses of ServiceEnpoint or nil.
|
92
|
-
# This method is useful for extracting several types of services while
|
93
|
-
# maintaining priority, for example you may write a filter Proc to extract
|
94
|
-
# OpenID and LID ServiceEnpoint objects.
|
95
|
-
def filter_services(filter)
|
96
|
-
# product a list of filtered ServiceEndpoint objects. filtered
|
97
|
-
# will contain a list of nil or ServiceEnpoint (subclasses) objects.
|
98
|
-
filtered = self.services.collect {|s| filter.call(s)}
|
99
|
-
|
100
|
-
# return all object in filtered that are not nil
|
101
|
-
return filtered.find_all {|s| s}
|
102
|
-
end
|
103
|
-
|
104
|
-
end
|