1
2
3 from urljr import fetchers
4
5 from openid import oidutil
6
7
8
9 try:
10 import yadis
11 except ImportError:
12 yadis_available = False
13
14 oidutil.log('Consumer operating without Yadis support '
15 '(failed to import Yadis library)')
16
18 """A failure to discover an OpenID server.
19
20 When the C{yadis} package is available, this is
21 C{yadis.discover.DiscoveryFailure}."""
22 else:
23 yadis_available = True
24 from yadis.etxrd import nsTag, XRDSError
25 from yadis.services import applyFilter as extractServices
26 from yadis.discover import discover as yadisDiscover
27 from yadis.discover import DiscoveryFailure
28 from yadis import xrires, filters
29
30 from openid.consumer.parse import openIDDiscover as parseOpenIDLinkRel
31 from openid.consumer.parse import ParseError
32
33 OPENID_1_0_NS = 'http://openid.net/xmlns/1.0'
34 OPENID_1_2_TYPE = 'http://openid.net/signon/1.2'
35 OPENID_1_1_TYPE = 'http://openid.net/signon/1.1'
36 OPENID_1_0_TYPE = 'http://openid.net/signon/1.0'
37
39 """Object representing an OpenID service endpoint.
40
41 @ivar identity_url: the verified identifier.
42 @ivar canonicalID: For XRI, the persistent identifier.
43 """
44 openid_type_uris = [
45 OPENID_1_2_TYPE,
46 OPENID_1_1_TYPE,
47 OPENID_1_0_TYPE,
48 ]
49
51 self.identity_url = None
52 self.server_url = None
53 self.type_uris = []
54 self.delegate = None
55 self.canonicalID = None
56 self.used_yadis = False
57
59 return extension_uri in self.type_uris
60
61 - def parseService(self, yadis_url, uri, type_uris, service_element):
62 """Set the state of this object based on the contents of the
63 service element."""
64 self.type_uris = type_uris
65 self.identity_url = yadis_url
66 self.server_url = uri
67 self.delegate = findDelegate(service_element)
68 self.used_yadis = True
69
71 """Return the identifier that should be sent as the
72 openid.identity_url parameter to the server."""
73 if self.delegate is None:
74 return self.canonicalID or self.identity_url
75 else:
76 return self.delegate
77
79 """Create a new instance of this class from the endpoint
80 object passed in.
81
82 @return: None or OpenIDServiceEndpoint for this endpoint object"""
83 type_uris = endpoint.matchTypes(cls.openid_type_uris)
84
85
86
87 if type_uris and endpoint.uri is not None:
88 openid_endpoint = cls()
89 openid_endpoint.parseService(
90 endpoint.yadis_url,
91 endpoint.uri,
92 endpoint.type_uris,
93 endpoint.service_element)
94 else:
95 openid_endpoint = None
96
97 return openid_endpoint
98
99 fromBasicServiceEndpoint = classmethod(fromBasicServiceEndpoint)
100
102 """Parse the given document as HTML looking for an OpenID <link
103 rel=...>
104
105 @raises: openid.consumer.parse.ParseError
106 """
107 delegate_url, server_url = parseOpenIDLinkRel(html)
108 service = cls()
109 service.identity_url = uri
110 service.delegate = delegate_url
111 service.server_url = server_url
112 service.type_uris = [OPENID_1_0_TYPE]
113 return service
114
115 fromHTML = classmethod(fromHTML)
116
118 """Extract a openid:Delegate value from a Yadis Service element
119 represented as an ElementTree Element object. If no delegate is
120 found, returns None."""
121
122 delegate_tag = nsTag(OPENID_1_0_NS, 'Delegate')
123
124 delegates = service_element.findall(delegate_tag)
125 for delegate_element in delegates:
126 delegate = delegate_element.text
127 break
128 else:
129 delegate = None
130
131 return delegate
132
134 """Discover OpenID services for a URI. Tries Yadis and falls back
135 on old-style <link rel='...'> discovery if Yadis fails.
136
137 @param uri: normalized identity URL
138 @type uri: str
139
140 @return: (identity_url, services)
141 @rtype: (str, list(OpenIDServiceEndpoint))
142
143 @raises: DiscoveryFailure
144 """
145
146
147
148
149 response = yadisDiscover(uri)
150
151 identity_url = response.normalized_uri
152 try:
153 openid_services = extractServices(
154 response.normalized_uri, response.response_text,
155 OpenIDServiceEndpoint)
156 except XRDSError:
157
158 openid_services = []
159
160 if not openid_services:
161
162
163 if response.isXRDS():
164
165
166
167 return discoverNoYadis(uri)
168 else:
169 body = response.response_text
170
171
172
173 try:
174 service = OpenIDServiceEndpoint.fromHTML(identity_url, body)
175 except ParseError:
176 pass
177 else:
178 openid_services = [service]
179
180 return (identity_url, openid_services)
181
182
184 endpoints = []
185 try:
186 canonicalID, services = xrires.ProxyResolver().query(
187 iname, OpenIDServiceEndpoint.openid_type_uris)
188 flt = filters.mkFilter(OpenIDServiceEndpoint)
189 for service_element in services:
190 endpoints.extend(flt.getServiceEndpoints(iname, service_element))
191 except XRDSError:
192 oidutil.log('xrds error on ' + iname)
193
194 for endpoint in endpoints:
195
196
197 endpoint.canonicalID = canonicalID
198
199
200 return iname, endpoints
201
202
204 http_resp = fetchers.fetch(uri)
205 if http_resp.status != 200:
206 raise DiscoveryFailure(
207 'HTTP Response status from identity URL host is not 200. '
208 'Got status %r' % (http_resp.status,), http_resp)
209 identity_url = http_resp.final_url
210
211
212
213 try:
214 service = OpenIDServiceEndpoint.fromHTML(identity_url, http_resp.body)
215 except ParseError:
216 openid_services = []
217 else:
218 openid_services = [service]
219
220 return identity_url, openid_services
221
222 if yadis_available:
223 discover = discoverYadis
224 else:
225 discover = discoverNoYadis
226