Subversion Repositories Applications.annuaire

Rev

Rev 42 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
42 aurelien 1
<?php
2
 
3
/**
4
 * The OpenID and Yadis discovery implementation for OpenID 1.2.
5
 */
6
 
7
require_once "Auth/OpenID.php";
8
require_once "Auth/OpenID/Parse.php";
9
require_once "Services/Yadis/XRIRes.php";
10
require_once "Services/Yadis/Yadis.php";
11
 
12
define('_OPENID_1_0_NS', 'http://openid.net/xmlns/1.0');
13
define('_OPENID_1_2_TYPE', 'http://openid.net/signon/1.2');
14
define('_OPENID_1_1_TYPE', 'http://openid.net/signon/1.1');
15
define('_OPENID_1_0_TYPE', 'http://openid.net/signon/1.0');
16
 
17
/**
18
 * Object representing an OpenID service endpoint.
19
 */
20
class Auth_OpenID_ServiceEndpoint {
21
    function Auth_OpenID_ServiceEndpoint()
22
    {
23
        $this->identity_url = null;
24
        $this->server_url = null;
25
        $this->type_uris = array();
26
        $this->delegate = null;
27
        $this->canonicalID = null;
28
        $this->used_yadis = false; // whether this came from an XRDS
29
    }
30
 
31
    function usesExtension($extension_uri)
32
    {
33
        return in_array($extension_uri, $this->type_uris);
34
    }
35
 
36
    function parseService($yadis_url, $uri, $type_uris, $service_element)
37
    {
38
        // Set the state of this object based on the contents of the
39
        // service element.
40
        $this->type_uris = $type_uris;
41
        $this->identity_url = $yadis_url;
42
        $this->server_url = $uri;
43
        $this->delegate = Auth_OpenID_ServiceEndpoint::findDelegate(
44
                                                         $service_element);
45
        $this->used_yadis = true;
46
    }
47
 
48
    function findDelegate($service)
49
    {
50
        // Extract a openid:Delegate value from a Yadis Service
51
        // element.  If no delegate is found, returns null.
52
 
53
        // Try to register new namespace.
54
        $service->parser->registerNamespace('openid',
55
                                            'http://openid.net/xmlns/1.0');
56
 
57
        // XXX: should this die if there is more than one delegate
58
        // element?
59
        $delegates = $service->getElements("openid:Delegate");
60
 
61
        if ($delegates) {
62
            return $service->parser->content($delegates[0]);
63
        } else {
64
            return null;
65
        }
66
    }
67
 
68
    function getServerID()
69
    {
70
        // Return the identifier that should be sent as the
71
        // openid.identity_url parameter to the server.
72
        if ($this->delegate === null) {
73
            if ($this->canonicalID) {
74
                return $this->canonicalID;
75
            } else {
76
                return $this->identity_url;
77
            }
78
        } else {
79
            return $this->delegate;
80
        }
81
    }
82
 
83
    function fromHTML($uri, $html)
84
    {
85
        // Parse the given document as HTML looking for an OpenID <link
86
        // rel=...>
87
        $urls = Auth_OpenID_legacy_discover($html);
88
        if ($urls === false) {
89
            return null;
90
        }
91
 
92
        list($delegate_url, $server_url) = $urls;
93
 
94
        $service = new Auth_OpenID_ServiceEndpoint();
95
        $service->identity_url = $uri;
96
        $service->delegate = $delegate_url;
97
        $service->server_url = $server_url;
98
        $service->type_uris = array(_OPENID_1_0_TYPE);
99
        return $service;
100
    }
101
}
102
 
103
function filter_MatchesAnyOpenIDType(&$service)
104
{
105
    $uris = $service->getTypes();
106
 
107
    foreach ($uris as $uri) {
108
        if (in_array($uri,
109
                     array(_OPENID_1_0_TYPE,
110
                           _OPENID_1_1_TYPE,
111
                           _OPENID_1_2_TYPE))) {
112
            return true;
113
        }
114
    }
115
 
116
    return false;
117
}
118
 
119
function Auth_OpenID_makeOpenIDEndpoints($uri, $endpoints)
120
{
121
    $s = array();
122
 
123
    if (!$endpoints) {
124
        return $s;
125
    }
126
 
127
    foreach ($endpoints as $service) {
128
        $type_uris = $service->getTypes();
129
        $uris = $service->getURIs();
130
 
131
        // If any Type URIs match and there is an endpoint URI
132
        // specified, then this is an OpenID endpoint
133
        if ($type_uris &&
134
            $uris) {
135
 
136
            foreach ($uris as $service_uri) {
137
                $openid_endpoint = new Auth_OpenID_ServiceEndpoint();
138
                $openid_endpoint->parseService($uri,
139
                                               $service_uri,
140
                                               $type_uris,
141
                                               $service);
142
 
143
                $s[] = $openid_endpoint;
144
            }
145
        }
146
    }
147
 
148
    return $s;
149
}
150
 
151
function Auth_OpenID_discoverWithYadis($uri, &$fetcher)
152
{
153
    // Discover OpenID services for a URI. Tries Yadis and falls back
154
    // on old-style <link rel='...'> discovery if Yadis fails.
155
 
156
    // Might raise a yadis.discover.DiscoveryFailure if no document
157
    // came back for that URI at all.  I don't think falling back to
158
    // OpenID 1.0 discovery on the same URL will help, so don't bother
159
    // to catch it.
160
    $openid_services = array();
161
 
162
    $http_response = null;
163
    $response = Services_Yadis_Yadis::discover($uri, $http_response,
164
                                                $fetcher);
165
 
166
    if ($response) {
167
        $identity_url = $response->uri;
168
        $openid_services =
169
            $response->xrds->services(array('filter_MatchesAnyOpenIDType'));
170
    }
171
 
172
    if (!$openid_services) {
173
        return @Auth_OpenID_discoverWithoutYadis($uri,
174
                                                 $fetcher);
175
    }
176
 
177
    if (!$openid_services) {
178
        $body = $response->body;
179
 
180
        // Try to parse the response as HTML to get OpenID 1.0/1.1
181
        // <link rel="...">
182
        $service = Auth_OpenID_ServiceEndpoint::fromHTML($identity_url,
183
                                                         $body);
184
 
185
        if ($service !== null) {
186
            $openid_services = array($service);
187
        }
188
    } else {
189
        $openid_services = Auth_OpenID_makeOpenIDEndpoints($response->uri,
190
                                                           $openid_services);
191
    }
192
 
193
    return array($identity_url, $openid_services, $http_response);
194
}
195
 
196
function _Auth_OpenID_discoverServiceList($uri, &$fetcher)
197
{
198
    list($url, $services, $resp) = Auth_OpenID_discoverWithYadis($uri,
199
                                                                 $fetcher);
200
 
201
    return $services;
202
}
203
 
204
function _Auth_OpenID_discoverXRIServiceList($uri, &$fetcher)
205
{
206
    list($url, $services, $resp) = _Auth_OpenID_discoverXRI($uri,
207
                                                            $fetcher);
208
    return $services;
209
}
210
 
211
function Auth_OpenID_discoverWithoutYadis($uri, &$fetcher)
212
{
213
    $http_resp = @$fetcher->get($uri);
214
 
215
    if ($http_resp->status != 200) {
216
        return array(null, array(), $http_resp);
217
    }
218
 
219
    $identity_url = $http_resp->final_url;
220
 
221
    // Try to parse the response as HTML to get OpenID 1.0/1.1 <link
222
    // rel="...">
223
    $endpoint =& new Auth_OpenID_ServiceEndpoint();
224
    $service = $endpoint->fromHTML($identity_url, $http_resp->body);
225
    if ($service === null) {
226
        $openid_services = array();
227
    } else {
228
        $openid_services = array($service);
229
    }
230
 
231
    return array($identity_url, $openid_services, $http_resp);
232
}
233
 
234
function _Auth_OpenID_discoverXRI($iname, &$fetcher)
235
{
236
    $services = new Services_Yadis_ProxyResolver($fetcher);
237
    list($canonicalID, $service_list) = $services->query($iname,
238
                                                  array(_OPENID_1_0_TYPE,
239
                                                        _OPENID_1_1_TYPE,
240
                                                        _OPENID_1_2_TYPE),
241
                                     array('filter_MatchesAnyOpenIDType'));
242
 
243
    $endpoints = Auth_OpenID_makeOpenIDEndpoints($iname, $service_list);
244
 
245
    for ($i = 0; $i < count($endpoints); $i++) {
246
        $endpoints[$i]->canonicalID = $canonicalID;
247
    }
248
 
249
    // FIXME: returned xri should probably be in some normal form
250
    return array($iname, $endpoints, null);
251
}
252
 
253
function Auth_OpenID_discover($uri, &$fetcher)
254
{
255
    return @Auth_OpenID_discoverWithYadis($uri, $fetcher);
256
}
257
 
258
?>