[ Index ]

PHP Cross Reference of Joomla 1.5.26 DE

title

Body

[close]

/libraries/openid/Auth/OpenID/ -> Discover.php (source)

   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  ?>


Generated: Wed Mar 28 15:54:07 2012 Cross-referenced by PHPXref 0.7.1