549 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			549 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * The OpenID and Yadis discovery implementation for OpenID 1.2.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								require_once "Auth/OpenID.php";
							 | 
						||
| 
								 | 
							
								require_once "Auth/OpenID/Parse.php";
							 | 
						||
| 
								 | 
							
								require_once "Auth/OpenID/Message.php";
							 | 
						||
| 
								 | 
							
								require_once "Auth/Yadis/XRIRes.php";
							 | 
						||
| 
								 | 
							
								require_once "Auth/Yadis/Yadis.php";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// XML namespace value
							 | 
						||
| 
								 | 
							
								define('Auth_OpenID_XMLNS_1_0', 'http://openid.net/xmlns/1.0');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Yadis service types
							 | 
						||
| 
								 | 
							
								define('Auth_OpenID_TYPE_1_2', 'http://openid.net/signon/1.2');
							 | 
						||
| 
								 | 
							
								define('Auth_OpenID_TYPE_1_1', 'http://openid.net/signon/1.1');
							 | 
						||
| 
								 | 
							
								define('Auth_OpenID_TYPE_1_0', 'http://openid.net/signon/1.0');
							 | 
						||
| 
								 | 
							
								define('Auth_OpenID_TYPE_2_0_IDP', 'http://specs.openid.net/auth/2.0/server');
							 | 
						||
| 
								 | 
							
								define('Auth_OpenID_TYPE_2_0', 'http://specs.openid.net/auth/2.0/signon');
							 | 
						||
| 
								 | 
							
								define('Auth_OpenID_RP_RETURN_TO_URL_TYPE',
							 | 
						||
| 
								 | 
							
								       'http://specs.openid.net/auth/2.0/return_to');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Auth_OpenID_getOpenIDTypeURIs()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return array(Auth_OpenID_TYPE_2_0_IDP,
							 | 
						||
| 
								 | 
							
								                 Auth_OpenID_TYPE_2_0,
							 | 
						||
| 
								 | 
							
								                 Auth_OpenID_TYPE_1_2,
							 | 
						||
| 
								 | 
							
								                 Auth_OpenID_TYPE_1_1,
							 | 
						||
| 
								 | 
							
								                 Auth_OpenID_TYPE_1_0,
							 | 
						||
| 
								 | 
							
								                 Auth_OpenID_RP_RETURN_TO_URL_TYPE);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Object representing an OpenID service endpoint.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								class Auth_OpenID_ServiceEndpoint {
							 | 
						||
| 
								 | 
							
								    function Auth_OpenID_ServiceEndpoint()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->claimed_id = null;
							 | 
						||
| 
								 | 
							
								        $this->server_url = null;
							 | 
						||
| 
								 | 
							
								        $this->type_uris = array();
							 | 
						||
| 
								 | 
							
								        $this->local_id = null;
							 | 
						||
| 
								 | 
							
								        $this->canonicalID = null;
							 | 
						||
| 
								 | 
							
								        $this->used_yadis = false; // whether this came from an XRDS
							 | 
						||
| 
								 | 
							
								        $this->display_identifier = null;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function getDisplayIdentifier()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if ($this->display_identifier) {
							 | 
						||
| 
								 | 
							
								            return $this->display_identifier;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (! $this->claimed_id) {
							 | 
						||
| 
								 | 
							
								          return $this->claimed_id;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $parsed = parse_url($this->claimed_id);
							 | 
						||
| 
								 | 
							
								        $scheme = $parsed['scheme'];
							 | 
						||
| 
								 | 
							
								        $host = $parsed['host'];
							 | 
						||
| 
								 | 
							
								        $path = $parsed['path'];
							 | 
						||
| 
								 | 
							
								        if (array_key_exists('query', $parsed)) {
							 | 
						||
| 
								 | 
							
								            $query = $parsed['query'];
							 | 
						||
| 
								 | 
							
								            $no_frag = "$scheme://$host$path?$query";
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            $no_frag = "$scheme://$host$path";
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return $no_frag;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function usesExtension($extension_uri)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return in_array($extension_uri, $this->type_uris);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function preferredNamespace()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (in_array(Auth_OpenID_TYPE_2_0_IDP, $this->type_uris) ||
							 | 
						||
| 
								 | 
							
								            in_array(Auth_OpenID_TYPE_2_0, $this->type_uris)) {
							 | 
						||
| 
								 | 
							
								            return Auth_OpenID_OPENID2_NS;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            return Auth_OpenID_OPENID1_NS;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     * Query this endpoint to see if it has any of the given type
							 | 
						||
| 
								 | 
							
								     * URIs. This is useful for implementing other endpoint classes
							 | 
						||
| 
								 | 
							
								     * that e.g. need to check for the presence of multiple versions
							 | 
						||
| 
								 | 
							
								     * of a single protocol.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param $type_uris The URIs that you wish to check
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @return all types that are in both in type_uris and
							 | 
						||
| 
								 | 
							
								     * $this->type_uris
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    function matchTypes($type_uris)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $result = array();
							 | 
						||
| 
								 | 
							
								        foreach ($type_uris as $test_uri) {
							 | 
						||
| 
								 | 
							
								            if ($this->supportsType($test_uri)) {
							 | 
						||
| 
								 | 
							
								                $result[] = $test_uri;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $result;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function supportsType($type_uri)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        // Does this endpoint support this type?
							 | 
						||
| 
								 | 
							
								        return ((in_array($type_uri, $this->type_uris)) ||
							 | 
						||
| 
								 | 
							
								                (($type_uri == Auth_OpenID_TYPE_2_0) &&
							 | 
						||
| 
								 | 
							
								                 $this->isOPIdentifier()));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function compatibilityMode()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return $this->preferredNamespace() != Auth_OpenID_OPENID2_NS;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function isOPIdentifier()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return in_array(Auth_OpenID_TYPE_2_0_IDP, $this->type_uris);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function fromOPEndpointURL($op_endpoint_url)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        // Construct an OP-Identifier OpenIDServiceEndpoint object for
							 | 
						||
| 
								 | 
							
								        // a given OP Endpoint URL
							 | 
						||
| 
								 | 
							
								        $obj = new Auth_OpenID_ServiceEndpoint();
							 | 
						||
| 
								 | 
							
								        $obj->server_url = $op_endpoint_url;
							 | 
						||
| 
								 | 
							
								        $obj->type_uris = array(Auth_OpenID_TYPE_2_0_IDP);
							 | 
						||
| 
								 | 
							
								        return $obj;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function parseService($yadis_url, $uri, $type_uris, $service_element)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        // Set the state of this object based on the contents of the
							 | 
						||
| 
								 | 
							
								        // service element.  Return true if successful, false if not
							 | 
						||
| 
								 | 
							
								        // (if findOPLocalIdentifier returns false).
							 | 
						||
| 
								 | 
							
								        $this->type_uris = $type_uris;
							 | 
						||
| 
								 | 
							
								        $this->server_url = $uri;
							 | 
						||
| 
								 | 
							
								        $this->used_yadis = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (!$this->isOPIdentifier()) {
							 | 
						||
| 
								 | 
							
								            $this->claimed_id = $yadis_url;
							 | 
						||
| 
								 | 
							
								            $this->local_id = Auth_OpenID_findOPLocalIdentifier(
							 | 
						||
| 
								 | 
							
								                                                    $service_element,
							 | 
						||
| 
								 | 
							
								                                                    $this->type_uris);
							 | 
						||
| 
								 | 
							
								            if ($this->local_id === false) {
							 | 
						||
| 
								 | 
							
								                return false;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function getLocalID()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        // Return the identifier that should be sent as the
							 | 
						||
| 
								 | 
							
								        // openid.identity_url parameter to the server.
							 | 
						||
| 
								 | 
							
								        if ($this->local_id === null && $this->canonicalID === null) {
							 | 
						||
| 
								 | 
							
								            return $this->claimed_id;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            if ($this->local_id) {
							 | 
						||
| 
								 | 
							
								                return $this->local_id;
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                return $this->canonicalID;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     * Parse the given document as XRDS looking for OpenID services.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @return array of Auth_OpenID_ServiceEndpoint or null if the
							 | 
						||
| 
								 | 
							
								     * document cannot be parsed.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    function fromXRDS($uri, $xrds_text)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $xrds =& Auth_Yadis_XRDS::parseXRDS($xrds_text);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if ($xrds) {
							 | 
						||
| 
								 | 
							
								            $yadis_services =
							 | 
						||
| 
								 | 
							
								              $xrds->services(array('filter_MatchesAnyOpenIDType'));
							 | 
						||
| 
								 | 
							
								            return Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return null;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /*
							 | 
						||
| 
								 | 
							
								     * Create endpoints from a DiscoveryResult.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param discoveryResult Auth_Yadis_DiscoveryResult
							 | 
						||
| 
								 | 
							
								     * @return array of Auth_OpenID_ServiceEndpoint or null if
							 | 
						||
| 
								 | 
							
								     * endpoints cannot be created.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    function fromDiscoveryResult($discoveryResult)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if ($discoveryResult->isXRDS()) {
							 | 
						||
| 
								 | 
							
								            return Auth_OpenID_ServiceEndpoint::fromXRDS(
							 | 
						||
| 
								 | 
							
								                                     $discoveryResult->normalized_uri,
							 | 
						||
| 
								 | 
							
								                                     $discoveryResult->response_text);
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            return Auth_OpenID_ServiceEndpoint::fromHTML(
							 | 
						||
| 
								 | 
							
								                                     $discoveryResult->normalized_uri,
							 | 
						||
| 
								 | 
							
								                                     $discoveryResult->response_text);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function fromHTML($uri, $html)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $discovery_types = array(
							 | 
						||
| 
								 | 
							
								                                 array(Auth_OpenID_TYPE_2_0,
							 | 
						||
| 
								 | 
							
								                                       'openid2.provider', 'openid2.local_id'),
							 | 
						||
| 
								 | 
							
								                                 array(Auth_OpenID_TYPE_1_1,
							 | 
						||
| 
								 | 
							
								                                       'openid.server', 'openid.delegate')
							 | 
						||
| 
								 | 
							
								                                 );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $services = array();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        foreach ($discovery_types as $triple) {
							 | 
						||
| 
								 | 
							
								            list($type_uri, $server_rel, $delegate_rel) = $triple;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            $urls = Auth_OpenID_legacy_discover($html, $server_rel,
							 | 
						||
| 
								 | 
							
								                                                $delegate_rel);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if ($urls === false) {
							 | 
						||
| 
								 | 
							
								                continue;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            list($delegate_url, $server_url) = $urls;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            $service = new Auth_OpenID_ServiceEndpoint();
							 | 
						||
| 
								 | 
							
								            $service->claimed_id = $uri;
							 | 
						||
| 
								 | 
							
								            $service->local_id = $delegate_url;
							 | 
						||
| 
								 | 
							
								            $service->server_url = $server_url;
							 | 
						||
| 
								 | 
							
								            $service->type_uris = array($type_uri);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            $services[] = $service;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $services;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function copy()
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $x = new Auth_OpenID_ServiceEndpoint();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $x->claimed_id = $this->claimed_id;
							 | 
						||
| 
								 | 
							
								        $x->server_url = $this->server_url;
							 | 
						||
| 
								 | 
							
								        $x->type_uris = $this->type_uris;
							 | 
						||
| 
								 | 
							
								        $x->local_id = $this->local_id;
							 | 
						||
| 
								 | 
							
								        $x->canonicalID = $this->canonicalID;
							 | 
						||
| 
								 | 
							
								        $x->used_yadis = $this->used_yadis;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return $x;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Auth_OpenID_findOPLocalIdentifier($service, $type_uris)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // Extract a openid:Delegate value from a Yadis Service element.
							 | 
						||
| 
								 | 
							
								    // If no delegate is found, returns null.  Returns false on
							 | 
						||
| 
								 | 
							
								    // discovery failure (when multiple delegate/localID tags have
							 | 
						||
| 
								 | 
							
								    // different values).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $service->parser->registerNamespace('openid',
							 | 
						||
| 
								 | 
							
								                                        Auth_OpenID_XMLNS_1_0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $service->parser->registerNamespace('xrd',
							 | 
						||
| 
								 | 
							
								                                        Auth_Yadis_XMLNS_XRD_2_0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $parser =& $service->parser;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $permitted_tags = array();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (in_array(Auth_OpenID_TYPE_1_1, $type_uris) ||
							 | 
						||
| 
								 | 
							
								        in_array(Auth_OpenID_TYPE_1_0, $type_uris)) {
							 | 
						||
| 
								 | 
							
								        $permitted_tags[] = 'openid:Delegate';
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (in_array(Auth_OpenID_TYPE_2_0, $type_uris)) {
							 | 
						||
| 
								 | 
							
								        $permitted_tags[] = 'xrd:LocalID';
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $local_id = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    foreach ($permitted_tags as $tag_name) {
							 | 
						||
| 
								 | 
							
								        $tags = $service->getElements($tag_name);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        foreach ($tags as $tag) {
							 | 
						||
| 
								 | 
							
								            $content = $parser->content($tag);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if ($local_id === null) {
							 | 
						||
| 
								 | 
							
								                $local_id = $content;
							 | 
						||
| 
								 | 
							
								            } else if ($local_id != $content) {
							 | 
						||
| 
								 | 
							
								                return false;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return $local_id;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function filter_MatchesAnyOpenIDType(&$service)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    $uris = $service->getTypes();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    foreach ($uris as $uri) {
							 | 
						||
| 
								 | 
							
								        if (in_array($uri, Auth_OpenID_getOpenIDTypeURIs())) {
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Auth_OpenID_bestMatchingService($service, $preferred_types)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // Return the index of the first matching type, or something
							 | 
						||
| 
								 | 
							
								    // higher if no type matches.
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // This provides an ordering in which service elements that
							 | 
						||
| 
								 | 
							
								    // contain a type that comes earlier in the preferred types list
							 | 
						||
| 
								 | 
							
								    // come before service elements that come later. If a service
							 | 
						||
| 
								 | 
							
								    // element has more than one type, the most preferred one wins.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    foreach ($preferred_types as $index => $typ) {
							 | 
						||
| 
								 | 
							
								        if (in_array($typ, $service->type_uris)) {
							 | 
						||
| 
								 | 
							
								            return $index;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return count($preferred_types);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Auth_OpenID_arrangeByType($service_list, $preferred_types)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // Rearrange service_list in a new list so services are ordered by
							 | 
						||
| 
								 | 
							
								    // types listed in preferred_types.  Return the new list.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Build a list with the service elements in tuples whose
							 | 
						||
| 
								 | 
							
								    // comparison will prefer the one with the best matching service
							 | 
						||
| 
								 | 
							
								    $prio_services = array();
							 | 
						||
| 
								 | 
							
								    foreach ($service_list as $index => $service) {
							 | 
						||
| 
								 | 
							
								        $prio_services[] = array(Auth_OpenID_bestMatchingService($service,
							 | 
						||
| 
								 | 
							
								                                                        $preferred_types),
							 | 
						||
| 
								 | 
							
								                                 $index, $service);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    sort($prio_services);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Now that the services are sorted by priority, remove the sort
							 | 
						||
| 
								 | 
							
								    // keys from the list.
							 | 
						||
| 
								 | 
							
								    foreach ($prio_services as $index => $s) {
							 | 
						||
| 
								 | 
							
								        $prio_services[$index] = $prio_services[$index][2];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return $prio_services;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Extract OP Identifier services.  If none found, return the rest,
							 | 
						||
| 
								 | 
							
								// sorted with most preferred first according to
							 | 
						||
| 
								 | 
							
								// OpenIDServiceEndpoint.openid_type_uris.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// openid_services is a list of OpenIDServiceEndpoint objects.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Returns a list of OpenIDServiceEndpoint objects."""
							 | 
						||
| 
								 | 
							
								function Auth_OpenID_getOPOrUserServices($openid_services)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    $op_services = Auth_OpenID_arrangeByType($openid_services,
							 | 
						||
| 
								 | 
							
								                                     array(Auth_OpenID_TYPE_2_0_IDP));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $openid_services = Auth_OpenID_arrangeByType($openid_services,
							 | 
						||
| 
								 | 
							
								                                     Auth_OpenID_getOpenIDTypeURIs());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ($op_services) {
							 | 
						||
| 
								 | 
							
								        return $op_services;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        return $openid_services;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    $s = array();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!$yadis_services) {
							 | 
						||
| 
								 | 
							
								        return $s;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    foreach ($yadis_services as $service) {
							 | 
						||
| 
								 | 
							
								        $type_uris = $service->getTypes();
							 | 
						||
| 
								 | 
							
								        $uris = $service->getURIs();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // If any Type URIs match and there is an endpoint URI
							 | 
						||
| 
								 | 
							
								        // specified, then this is an OpenID endpoint
							 | 
						||
| 
								 | 
							
								        if ($type_uris &&
							 | 
						||
| 
								 | 
							
								            $uris) {
							 | 
						||
| 
								 | 
							
								            foreach ($uris as $service_uri) {
							 | 
						||
| 
								 | 
							
								                $openid_endpoint = new Auth_OpenID_ServiceEndpoint();
							 | 
						||
| 
								 | 
							
								                if ($openid_endpoint->parseService($uri,
							 | 
						||
| 
								 | 
							
								                                                   $service_uri,
							 | 
						||
| 
								 | 
							
								                                                   $type_uris,
							 | 
						||
| 
								 | 
							
								                                                   $service)) {
							 | 
						||
| 
								 | 
							
								                    $s[] = $openid_endpoint;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return $s;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Auth_OpenID_discoverWithYadis($uri, &$fetcher,
							 | 
						||
| 
								 | 
							
								              $endpoint_filter='Auth_OpenID_getOPOrUserServices',
							 | 
						||
| 
								 | 
							
								              $discover_function=null)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // Discover OpenID services for a URI. Tries Yadis and falls back
							 | 
						||
| 
								 | 
							
								    // on old-style <link rel='...'> discovery if Yadis fails.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Might raise a yadis.discover.DiscoveryFailure if no document
							 | 
						||
| 
								 | 
							
								    // came back for that URI at all.  I don't think falling back to
							 | 
						||
| 
								 | 
							
								    // OpenID 1.0 discovery on the same URL will help, so don't bother
							 | 
						||
| 
								 | 
							
								    // to catch it.
							 | 
						||
| 
								 | 
							
								    if ($discover_function === null) {
							 | 
						||
| 
								 | 
							
								        $discover_function = array('Auth_Yadis_Yadis', 'discover');
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $openid_services = array();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $response = call_user_func_array($discover_function,
							 | 
						||
| 
								 | 
							
								                                     array($uri, &$fetcher));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $yadis_url = $response->normalized_uri;
							 | 
						||
| 
								 | 
							
								    $yadis_services = array();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ($response->isFailure()) {
							 | 
						||
| 
								 | 
							
								        return array($uri, array());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $openid_services = Auth_OpenID_ServiceEndpoint::fromXRDS(
							 | 
						||
| 
								 | 
							
								                                         $yadis_url,
							 | 
						||
| 
								 | 
							
								                                         $response->response_text);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!$openid_services) {
							 | 
						||
| 
								 | 
							
								        if ($response->isXRDS()) {
							 | 
						||
| 
								 | 
							
								            return Auth_OpenID_discoverWithoutYadis($uri,
							 | 
						||
| 
								 | 
							
								                                                    $fetcher);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Try to parse the response as HTML to get OpenID 1.0/1.1
							 | 
						||
| 
								 | 
							
								        // <link rel="...">
							 | 
						||
| 
								 | 
							
								        $openid_services = Auth_OpenID_ServiceEndpoint::fromHTML(
							 | 
						||
| 
								 | 
							
								                                        $yadis_url,
							 | 
						||
| 
								 | 
							
								                                        $response->response_text);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $openid_services = call_user_func_array($endpoint_filter,
							 | 
						||
| 
								 | 
							
								                                            array(&$openid_services));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return array($yadis_url, $openid_services);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Auth_OpenID_discoverURI($uri, &$fetcher)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    $uri = Auth_OpenID::normalizeUrl($uri);
							 | 
						||
| 
								 | 
							
								    return Auth_OpenID_discoverWithYadis($uri, $fetcher);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Auth_OpenID_discoverWithoutYadis($uri, &$fetcher)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    $http_resp = @$fetcher->get($uri);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ($http_resp->status != 200 and $http_resp->status != 206) {
							 | 
						||
| 
								 | 
							
								        return array($uri, array());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $identity_url = $http_resp->final_url;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Try to parse the response as HTML to get OpenID 1.0/1.1 <link
							 | 
						||
| 
								 | 
							
								    // rel="...">
							 | 
						||
| 
								 | 
							
								    $openid_services = Auth_OpenID_ServiceEndpoint::fromHTML(
							 | 
						||
| 
								 | 
							
								                                           $identity_url,
							 | 
						||
| 
								 | 
							
								                                           $http_resp->body);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return array($identity_url, $openid_services);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Auth_OpenID_discoverXRI($iname, &$fetcher)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    $resolver = new Auth_Yadis_ProxyResolver($fetcher);
							 | 
						||
| 
								 | 
							
								    list($canonicalID, $yadis_services) =
							 | 
						||
| 
								 | 
							
								        $resolver->query($iname,
							 | 
						||
| 
								 | 
							
								                         Auth_OpenID_getOpenIDTypeURIs(),
							 | 
						||
| 
								 | 
							
								                         array('filter_MatchesAnyOpenIDType'));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $openid_services = Auth_OpenID_makeOpenIDEndpoints($iname,
							 | 
						||
| 
								 | 
							
								                                                       $yadis_services);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    $openid_services = Auth_OpenID_getOPOrUserServices($openid_services);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for ($i = 0; $i < count($openid_services); $i++) {
							 | 
						||
| 
								 | 
							
								        $openid_services[$i]->canonicalID = $canonicalID;
							 | 
						||
| 
								 | 
							
								        $openid_services[$i]->claimed_id = $canonicalID;
							 | 
						||
| 
								 | 
							
								        $openid_services[$i]->display_identifier = $iname;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // FIXME: returned xri should probably be in some normal form
							 | 
						||
| 
								 | 
							
								    return array($iname, $openid_services);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Auth_OpenID_discover($uri, &$fetcher)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    // If the fetcher (i.e., PHP) doesn't support SSL, we can't do
							 | 
						||
| 
								 | 
							
								    // discovery on an HTTPS URL.
							 | 
						||
| 
								 | 
							
								    if ($fetcher->isHTTPS($uri) && !$fetcher->supportsSSL()) {
							 | 
						||
| 
								 | 
							
								        return array($uri, array());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (Auth_Yadis_identifierScheme($uri) == 'XRI') {
							 | 
						||
| 
								 | 
							
								        $result = Auth_OpenID_discoverXRI($uri, $fetcher);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        $result = Auth_OpenID_discoverURI($uri, $fetcher);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // If the fetcher doesn't support SSL, we can't interact with
							 | 
						||
| 
								 | 
							
								    // HTTPS server URLs; remove those endpoints from the list.
							 | 
						||
| 
								 | 
							
								    if (!$fetcher->supportsSSL()) {
							 | 
						||
| 
								 | 
							
								        $http_endpoints = array();
							 | 
						||
| 
								 | 
							
								        list($new_uri, $endpoints) = $result;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        foreach ($endpoints as $e) {
							 | 
						||
| 
								 | 
							
								            if (!$fetcher->isHTTPS($e->server_url)) {
							 | 
						||
| 
								 | 
							
								                $http_endpoints[] = $e;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $result = array($new_uri, $http_endpoints);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return $result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								?>
							 |