ruby-yadis 0.3.3 → 0.3.4
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/COPYING +13 -10
- data/README +3 -0
- metadata +5 -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/COPYING
CHANGED
@@ -1,10 +1,13 @@
|
|
1
|
-
Copyright
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
Copyright 2006 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.
|
data/README
CHANGED
@@ -9,6 +9,9 @@ Yadis Specification details:
|
|
9
9
|
|
10
10
|
Please see the INSTALL, and have a look at the YADIS interface in yadis/yadis.rb
|
11
11
|
|
12
|
+
==License
|
13
|
+
Apache Software License. For more information see the LICENSE file.
|
14
|
+
|
12
15
|
==Authors
|
13
16
|
Brian Ellin. brian -at- janrain -dot- com
|
14
17
|
JanRain, Inc. http://www.janrain.com/
|
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: 0.3.
|
7
|
-
date:
|
6
|
+
version: 0.3.4
|
7
|
+
date: 2007-01-04 00:00:00 -08: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
|
- lib/yadis/xri.rb
|
48
42
|
- lib/yadis/xrires.rb
|
49
43
|
- test/test_parse.rb
|
@@ -55,12 +49,12 @@ files:
|
|
55
49
|
- test/test_xri.rb
|
56
50
|
- test/data/manifest.txt
|
57
51
|
- test/data/brian.xrds
|
58
|
-
- test/data/index.html
|
59
|
-
- test/data/brian.multi.xrds
|
60
52
|
- test/data/brian_priority.xrds
|
53
|
+
- test/data/brian.multi.xrds
|
54
|
+
- test/data/index.html
|
61
55
|
- test/data/brian.multi_uri.xrds
|
62
|
-
- test/data/index_xrds.html
|
63
56
|
- test/data/index_yadis.html
|
57
|
+
- test/data/index_xrds.html
|
64
58
|
- test/data/proxy-june1.xrds
|
65
59
|
- test/data/weirdver.xrds
|
66
60
|
- test/data/keturn.xrds
|
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
|