| [ Index ] |
PHP Cross Reference of Joomla 1.5.26 DE |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * The OpenID and Yadis discovery implementation for OpenID 1.2. 5 */ 6 7 // Do not allow direct access 8 defined( '_JEXEC' ) or die( 'Restricted access' ); 9 10 require_once "Auth/OpenID.php"; 11 require_once "Auth/OpenID/Parse.php"; 12 require_once "Auth/OpenID/Message.php"; 13 require_once "Auth/Yadis/XRIRes.php"; 14 require_once "Auth/Yadis/Yadis.php"; 15 16 // XML namespace value 17 define('Auth_OpenID_XMLNS_1_0', 'http://openid.net/xmlns/1.0'); 18 19 // Yadis service types 20 define('Auth_OpenID_TYPE_1_2', 'http://openid.net/signon/1.2'); 21 define('Auth_OpenID_TYPE_1_1', 'http://openid.net/signon/1.1'); 22 define('Auth_OpenID_TYPE_1_0', 'http://openid.net/signon/1.0'); 23 define('Auth_OpenID_TYPE_2_0_IDP', 'http://specs.openid.net/auth/2.0/server'); 24 define('Auth_OpenID_TYPE_2_0', 'http://specs.openid.net/auth/2.0/signon'); 25 define('Auth_OpenID_RP_RETURN_TO_URL_TYPE', 26 'http://specs.openid.net/auth/2.0/return_to'); 27 28 function Auth_OpenID_getOpenIDTypeURIs() 29 { 30 return array(Auth_OpenID_TYPE_2_0_IDP, 31 Auth_OpenID_TYPE_2_0, 32 Auth_OpenID_TYPE_1_2, 33 Auth_OpenID_TYPE_1_1, 34 Auth_OpenID_TYPE_1_0, 35 Auth_OpenID_RP_RETURN_TO_URL_TYPE); 36 } 37 38 /** 39 * Object representing an OpenID service endpoint. 40 */ 41 class Auth_OpenID_ServiceEndpoint { 42 function Auth_OpenID_ServiceEndpoint() 43 { 44 $this->claimed_id = null; 45 $this->server_url = null; 46 $this->type_uris = array(); 47 $this->local_id = null; 48 $this->canonicalID = null; 49 $this->used_yadis = false; // whether this came from an XRDS 50 $this->display_identifier = null; 51 } 52 53 function getDisplayIdentifier() 54 { 55 if ($this->display_identifier) { 56 return $this->display_identifier; 57 } 58 if (! $this->claimed_id) { 59 return $this->claimed_id; 60 } 61 $parsed = parse_url($this->claimed_id); 62 $scheme = $parsed['scheme']; 63 $host = $parsed['host']; 64 $path = $parsed['path']; 65 if (array_key_exists('query', $parsed)) { 66 $query = $parsed['query']; 67 $no_frag = "$scheme://$host$path?$query"; 68 } else { 69 $no_frag = "$scheme://$host$path"; 70 } 71 return $no_frag; 72 } 73 74 function usesExtension($extension_uri) 75 { 76 return in_array($extension_uri, $this->type_uris); 77 } 78 79 function preferredNamespace() 80 { 81 if (in_array(Auth_OpenID_TYPE_2_0_IDP, $this->type_uris) || 82 in_array(Auth_OpenID_TYPE_2_0, $this->type_uris)) { 83 return Auth_OpenID_OPENID2_NS; 84 } else { 85 return Auth_OpenID_OPENID1_NS; 86 } 87 } 88 89 /* 90 * Query this endpoint to see if it has any of the given type 91 * URIs. This is useful for implementing other endpoint classes 92 * that e.g. need to check for the presence of multiple versions 93 * of a single protocol. 94 * 95 * @param $type_uris The URIs that you wish to check 96 * 97 * @return all types that are in both in type_uris and 98 * $this->type_uris 99 */ 100 function matchTypes($type_uris) 101 { 102 $result = array(); 103 foreach ($type_uris as $test_uri) { 104 if ($this->supportsType($test_uri)) { 105 $result[] = $test_uri; 106 } 107 } 108 109 return $result; 110 } 111 112 function supportsType($type_uri) 113 { 114 // Does this endpoint support this type? 115 return ((in_array($type_uri, $this->type_uris)) || 116 (($type_uri == Auth_OpenID_TYPE_2_0) && 117 $this->isOPIdentifier())); 118 } 119 120 function compatibilityMode() 121 { 122 return $this->preferredNamespace() != Auth_OpenID_OPENID2_NS; 123 } 124 125 function isOPIdentifier() 126 { 127 return in_array(Auth_OpenID_TYPE_2_0_IDP, $this->type_uris); 128 } 129 130 function fromOPEndpointURL($op_endpoint_url) 131 { 132 // Construct an OP-Identifier OpenIDServiceEndpoint object for 133 // a given OP Endpoint URL 134 $obj = new Auth_OpenID_ServiceEndpoint(); 135 $obj->server_url = $op_endpoint_url; 136 $obj->type_uris = array(Auth_OpenID_TYPE_2_0_IDP); 137 return $obj; 138 } 139 140 function parseService($yadis_url, $uri, $type_uris, $service_element) 141 { 142 // Set the state of this object based on the contents of the 143 // service element. Return true if successful, false if not 144 // (if findOPLocalIdentifier returns false). 145 $this->type_uris = $type_uris; 146 $this->server_url = $uri; 147 $this->used_yadis = true; 148 149 if (!$this->isOPIdentifier()) { 150 $this->claimed_id = $yadis_url; 151 $this->local_id = Auth_OpenID_findOPLocalIdentifier( 152 $service_element, 153 $this->type_uris); 154 if ($this->local_id === false) { 155 return false; 156 } 157 } 158 159 return true; 160 } 161 162 function getLocalID() 163 { 164 // Return the identifier that should be sent as the 165 // openid.identity_url parameter to the server. 166 if ($this->local_id === null && $this->canonicalID === null) { 167 return $this->claimed_id; 168 } else { 169 if ($this->local_id) { 170 return $this->local_id; 171 } else { 172 return $this->canonicalID; 173 } 174 } 175 } 176 177 /* 178 * Parse the given document as XRDS looking for OpenID services. 179 * 180 * @return array of Auth_OpenID_ServiceEndpoint or null if the 181 * document cannot be parsed. 182 */ 183 function fromXRDS($uri, $xrds_text) 184 { 185 $xrds =& Auth_Yadis_XRDS::parseXRDS($xrds_text); 186 187 if ($xrds) { 188 $yadis_services = 189 $xrds->services(array('filter_MatchesAnyOpenIDType')); 190 return Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services); 191 } 192 193 return null; 194 } 195 196 /* 197 * Create endpoints from a DiscoveryResult. 198 * 199 * @param discoveryResult Auth_Yadis_DiscoveryResult 200 * @return array of Auth_OpenID_ServiceEndpoint or null if 201 * endpoints cannot be created. 202 */ 203 function fromDiscoveryResult($discoveryResult) 204 { 205 if ($discoveryResult->isXRDS()) { 206 return Auth_OpenID_ServiceEndpoint::fromXRDS( 207 $discoveryResult->normalized_uri, 208 $discoveryResult->response_text); 209 } else { 210 return Auth_OpenID_ServiceEndpoint::fromHTML( 211 $discoveryResult->normalized_uri, 212 $discoveryResult->response_text); 213 } 214 } 215 216 function fromHTML($uri, $html) 217 { 218 $discovery_types = array( 219 array(Auth_OpenID_TYPE_2_0, 220 'openid2.provider', 'openid2.local_id'), 221 array(Auth_OpenID_TYPE_1_1, 222 'openid.server', 'openid.delegate') 223 ); 224 225 $services = array(); 226 227 foreach ($discovery_types as $triple) { 228 list($type_uri, $server_rel, $delegate_rel) = $triple; 229 230 $urls = Auth_OpenID_legacy_discover($html, $server_rel, 231 $delegate_rel); 232 233 if ($urls === false) { 234 continue; 235 } 236 237 list($delegate_url, $server_url) = $urls; 238 239 $service = new Auth_OpenID_ServiceEndpoint(); 240 $service->claimed_id = $uri; 241 $service->local_id = $delegate_url; 242 $service->server_url = $server_url; 243 $service->type_uris = array($type_uri); 244 245 $services[] = $service; 246 } 247 248 return $services; 249 } 250 251 function copy() 252 { 253 $x = new Auth_OpenID_ServiceEndpoint(); 254 255 $x->claimed_id = $this->claimed_id; 256 $x->server_url = $this->server_url; 257 $x->type_uris = $this->type_uris; 258 $x->local_id = $this->local_id; 259 $x->canonicalID = $this->canonicalID; 260 $x->used_yadis = $this->used_yadis; 261 262 return $x; 263 } 264 } 265 266 function Auth_OpenID_findOPLocalIdentifier($service, $type_uris) 267 { 268 // Extract a openid:Delegate value from a Yadis Service element. 269 // If no delegate is found, returns null. Returns false on 270 // discovery failure (when multiple delegate/localID tags have 271 // different values). 272 273 $service->parser->registerNamespace('openid', 274 Auth_OpenID_XMLNS_1_0); 275 276 $service->parser->registerNamespace('xrd', 277 Auth_Yadis_XMLNS_XRD_2_0); 278 279 $parser =& $service->parser; 280 281 $permitted_tags = array(); 282 283 if (in_array(Auth_OpenID_TYPE_1_1, $type_uris) || 284 in_array(Auth_OpenID_TYPE_1_0, $type_uris)) { 285 $permitted_tags[] = 'openid:Delegate'; 286 } 287 288 if (in_array(Auth_OpenID_TYPE_2_0, $type_uris)) { 289 $permitted_tags[] = 'xrd:LocalID'; 290 } 291 292 $local_id = null; 293 294 foreach ($permitted_tags as $tag_name) { 295 $tags = $service->getElements($tag_name); 296 297 foreach ($tags as $tag) { 298 $content = $parser->content($tag); 299 300 if ($local_id === null) { 301 $local_id = $content; 302 } else if ($local_id != $content) { 303 return false; 304 } 305 } 306 } 307 308 return $local_id; 309 } 310 311 function filter_MatchesAnyOpenIDType(&$service) 312 { 313 $uris = $service->getTypes(); 314 315 foreach ($uris as $uri) { 316 if (in_array($uri, Auth_OpenID_getOpenIDTypeURIs())) { 317 return true; 318 } 319 } 320 321 return false; 322 } 323 324 function Auth_OpenID_bestMatchingService($service, $preferred_types) 325 { 326 // Return the index of the first matching type, or something 327 // higher if no type matches. 328 // 329 // This provides an ordering in which service elements that 330 // contain a type that comes earlier in the preferred types list 331 // come before service elements that come later. If a service 332 // element has more than one type, the most preferred one wins. 333 334 foreach ($preferred_types as $index => $typ) { 335 if (in_array($typ, $service->type_uris)) { 336 return $index; 337 } 338 } 339 340 return count($preferred_types); 341 } 342 343 function Auth_OpenID_arrangeByType($service_list, $preferred_types) 344 { 345 // Rearrange service_list in a new list so services are ordered by 346 // types listed in preferred_types. Return the new list. 347 348 // Build a list with the service elements in tuples whose 349 // comparison will prefer the one with the best matching service 350 $prio_services = array(); 351 foreach ($service_list as $index => $service) { 352 $prio_services[] = array(Auth_OpenID_bestMatchingService($service, 353 $preferred_types), 354 $index, $service); 355 } 356 357 sort($prio_services); 358 359 // Now that the services are sorted by priority, remove the sort 360 // keys from the list. 361 foreach ($prio_services as $index => $s) { 362 $prio_services[$index] = $prio_services[$index][2]; 363 } 364 365 return $prio_services; 366 } 367 368 // Extract OP Identifier services. If none found, return the rest, 369 // sorted with most preferred first according to 370 // OpenIDServiceEndpoint.openid_type_uris. 371 // 372 // openid_services is a list of OpenIDServiceEndpoint objects. 373 // 374 // Returns a list of OpenIDServiceEndpoint objects.""" 375 function Auth_OpenID_getOPOrUserServices($openid_services) 376 { 377 $op_services = Auth_OpenID_arrangeByType($openid_services, 378 array(Auth_OpenID_TYPE_2_0_IDP)); 379 380 $openid_services = Auth_OpenID_arrangeByType($openid_services, 381 Auth_OpenID_getOpenIDTypeURIs()); 382 383 if ($op_services) { 384 return $op_services; 385 } else { 386 return $openid_services; 387 } 388 } 389 390 function Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services) 391 { 392 $s = array(); 393 394 if (!$yadis_services) { 395 return $s; 396 } 397 398 foreach ($yadis_services as $service) { 399 $type_uris = $service->getTypes(); 400 $uris = $service->getURIs(); 401 402 // If any Type URIs match and there is an endpoint URI 403 // specified, then this is an OpenID endpoint 404 if ($type_uris && 405 $uris) { 406 foreach ($uris as $service_uri) { 407 $openid_endpoint = new Auth_OpenID_ServiceEndpoint(); 408 if ($openid_endpoint->parseService($uri, 409 $service_uri, 410 $type_uris, 411 $service)) { 412 $s[] = $openid_endpoint; 413 } 414 } 415 } 416 } 417 418 return $s; 419 } 420 421 function Auth_OpenID_discoverWithYadis($uri, &$fetcher, 422 $endpoint_filter='Auth_OpenID_getOPOrUserServices', 423 $discover_function=null) 424 { 425 // Discover OpenID services for a URI. Tries Yadis and falls back 426 // on old-style <link rel='...'> discovery if Yadis fails. 427 428 // Might raise a yadis.discover.DiscoveryFailure if no document 429 // came back for that URI at all. I don't think falling back to 430 // OpenID 1.0 discovery on the same URL will help, so don't bother 431 // to catch it. 432 if ($discover_function === null) { 433 $discover_function = array('Auth_Yadis_Yadis', 'discover'); 434 } 435 436 $openid_services = array(); 437 438 $response = call_user_func_array($discover_function, 439 array($uri, &$fetcher)); 440 441 $yadis_url = $response->normalized_uri; 442 $yadis_services = array(); 443 444 if ($response->isFailure()) { 445 return array($uri, array()); 446 } 447 448 $openid_services = Auth_OpenID_ServiceEndpoint::fromXRDS( 449 $yadis_url, 450 $response->response_text); 451 452 if (!$openid_services) { 453 if ($response->isXRDS()) { 454 return Auth_OpenID_discoverWithoutYadis($uri, 455 $fetcher); 456 } 457 458 // Try to parse the response as HTML to get OpenID 1.0/1.1 459 // <link rel="..."> 460 $openid_services = Auth_OpenID_ServiceEndpoint::fromHTML( 461 $yadis_url, 462 $response->response_text); 463 } 464 465 $openid_services = call_user_func_array($endpoint_filter, 466 array(&$openid_services)); 467 468 return array($yadis_url, $openid_services); 469 } 470 471 function Auth_OpenID_discoverURI($uri, &$fetcher) 472 { 473 $uri = Auth_OpenID::normalizeUrl($uri); 474 return Auth_OpenID_discoverWithYadis($uri, $fetcher); 475 } 476 477 function Auth_OpenID_discoverWithoutYadis($uri, &$fetcher) 478 { 479 $http_resp = @$fetcher->get($uri); 480 481 if ($http_resp->status != 200 and $http_resp->status != 206) { 482 return array($uri, array()); 483 } 484 485 $identity_url = $http_resp->final_url; 486 487 // Try to parse the response as HTML to get OpenID 1.0/1.1 <link 488 // rel="..."> 489 $openid_services = Auth_OpenID_ServiceEndpoint::fromHTML( 490 $identity_url, 491 $http_resp->body); 492 493 return array($identity_url, $openid_services); 494 } 495 496 function Auth_OpenID_discoverXRI($iname, &$fetcher) 497 { 498 $resolver = new Auth_Yadis_ProxyResolver($fetcher); 499 list($canonicalID, $yadis_services) = 500 $resolver->query($iname, 501 Auth_OpenID_getOpenIDTypeURIs(), 502 array('filter_MatchesAnyOpenIDType')); 503 504 $openid_services = Auth_OpenID_makeOpenIDEndpoints($iname, 505 $yadis_services); 506 507 $openid_services = Auth_OpenID_getOPOrUserServices($openid_services); 508 509 for ($i = 0; $i < count($openid_services); $i++) { 510 $openid_services[$i]->canonicalID = $canonicalID; 511 $openid_services[$i]->claimed_id = $canonicalID; 512 $openid_services[$i]->display_identifier = $iname; 513 } 514 515 // FIXME: returned xri should probably be in some normal form 516 return array($iname, $openid_services); 517 } 518 519 function Auth_OpenID_discover($uri, &$fetcher) 520 { 521 // If the fetcher (i.e., PHP) doesn't support SSL, we can't do 522 // discovery on an HTTPS URL. 523 if ($fetcher->isHTTPS($uri) && !$fetcher->supportsSSL()) { 524 return array($uri, array()); 525 } 526 527 if (Auth_Yadis_identifierScheme($uri) == 'XRI') { 528 $result = Auth_OpenID_discoverXRI($uri, $fetcher); 529 } else { 530 $result = Auth_OpenID_discoverURI($uri, $fetcher); 531 } 532 533 // If the fetcher doesn't support SSL, we can't interact with 534 // HTTPS server URLs; remove those endpoints from the list. 535 if (!$fetcher->supportsSSL()) { 536 $http_endpoints = array(); 537 list($new_uri, $endpoints) = $result; 538 539 foreach ($endpoints as $e) { 540 if (!$fetcher->isHTTPS($e->server_url)) { 541 $http_endpoints[] = $e; 542 } 543 } 544 545 $result = array($new_uri, $http_endpoints); 546 } 547 548 return $result; 549 } 550 551 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Wed Mar 28 15:54:07 2012 | Cross-referenced by PHPXref 0.7.1 |