# OpenIdCredentials.class.php

Go to the documentation of this file.

    00001 <?php
    00002 /***************************************************************************
    00003  *   Copyright (C) 2007 by Anton E. Lebedevich                             *
    00004  *                                                                         *
    00005  *   This program is free software; you can redistribute it and/or modify  *
    00006  *   it under the terms of the GNU Lesser General Public License as        *
    00007  *   published by the Free Software Foundation; either version 3 of the    *
    00008  *   License, or (at your option) any later version.                       *
    00009  *                                                                         *
    00010  ***************************************************************************/
    00011
    00015     final class OpenIdCredentials
    00016     {
    00017         const HEADER_CONT_TYPE = 'application/xrds+xml';
    00018         const HEADER_XRDS_LOCATION = 'x-xrds-location';
    00019         const HEADER_ACCEPT = 'text/html,application/xhtml+xml,application/xml,application/xrds+xml';
    00020         const IDENTIFIER_SELECT = 'http://specs.openid.net/auth/2.0/identifier_select';
    00021
    00022         private $claimedId  = null;
    00023         private $realId     = null;
    00024         private $server     = null;
    00025         private $httpClient = null;
    00026         private $isIdentifierSelect = false;
    00027
    00028         public function __construct(
    00029             HttpUrl $claimedId,
    00030             HttpClient $httpClient
    00031         )
    00032         {
    00033             $this->claimedId = $claimedId->makeComparable();
    00034
    00035             if (!$claimedId->isValid())
    00036                 throw new OpenIdException('invalid claimed id');
    00037
    00038             $this->httpClient = $httpClient;
    00039
    00040             $response = $httpClient->send(
    00041                 HttpRequest::create()->
    00042                 setHeaderVar('Accept', self::HEADER_ACCEPT)->
    00043                 setMethod(HttpMethod::get())->
    00044                 setUrl($claimedId)
    00045             );
    00046
    00047             if ($response->getStatus()->getId() != 200) {
    00048                 throw new OpenIdException('can\'t fetch document');
    00049             }
    00050
    00051             $contentType = $response->getHeader('content-type');
    00052             if (mb_stripos($contentType, self::HEADER_CONT_TYPE) !== false) {
    00053                 $this->parseXRDS($response->getBody());
    00054             } elseif ($response->hasHeader(self::HEADER_XRDS_LOCATION)) {
    00055                 $this->loadXRDS($response->getHeader(self::HEADER_XRDS_LOCATION));
    00056             } else {
    00057                 $this->parseHTML($response->getBody());
    00058             }
    00059
    00060             if (!$this->server || !$this->server->isValid())
    00061                 throw new OpenIdException('bad server');
    00062             else
    00063                 $this->server->makeComparable();
    00064
    00065             if (!$this->realId)
    00066                 $this->realId = $claimedId;
    00067             elseif (!$this->realId->isValid())
    00068                 throw new OpenIdException('bad delegate');
    00069             else
    00070                 $this->realId->makeComparable();
    00071         }
    00072
    00076         public static function create(
    00077             HttpUrl $claimedId,
    00078             HttpClient $httpClient
    00079         )
    00080         {
    00081             return new self($claimedId, $httpClient);
    00082         }
    00083
    00087         public function getRealId()
    00088         {
    00089             if ($this->isIdentifierSelect()) {
    00090                 return  HttpUrl::create()->parse(self::IDENTIFIER_SELECT);
    00091             }
    00092
    00093             return $this->realId;
    00094         }
    00095
    00099         public function getServer()
    00100         {
    00101             return $this->server;
    00102         }
    00103
    00104         public function isIdentifierSelect()
    00105         {
    00106             return $this->isIdentifierSelect;
    00107         }
    00108
    00112         public function setIdentifierSelect($bool)
    00113         {
    00114             $this->isIdentifierSelect = (bool) $bool;
    00115
    00116             return $this;
    00117         }
    00118
    00119         protected function parseHTML($content)
    00120         {
    00121             $tokenizer = HtmlTokenizer::create(
    00122                     StringInputStream::create($content)
    00123                 )->
    00124                 lowercaseTags(true)->
    00125                 lowercaseAttributes(true);
    00126
    00127             $insideHead = false;
    00128             while ($token = $tokenizer->nextToken()) {
    00129                 if (!$insideHead) {
    00130                     if ($token instanceof SgmlOpenTag
    00131                         && $token->getId() == 'head'
    00132                     ) {
    00133                         $insideHead = true;
    00134                         continue;
    00135                     }
    00136                 }
    00137
    00138                 if ($insideHead) {
    00139                     if ($token instanceof SgmlEndTag && $token->getId() == 'head')
    00140                         break;
    00141
    00142                     if (
    00143                         $token instanceof SgmlOpenTag
    00144                         && $token->getId() == 'link'
    00145                         && $token->hasAttribute('rel')
    00146                         && $token->hasAttribute('href')
    00147                     ) {
    00148                         if ($token->getAttribute('rel') == 'openid.server')
    00149                             $this->server = HttpUrl::create()->parse(
    00150                                 $token->getAttribute('href')
    00151                             );
    00152
    00153                         if ($token->getAttribute('rel') == 'openid.delegate')
    00154                             $this->realId = HttpUrl::create()->parse(
    00155                                 $token->getAttribute('href')
    00156                             );
    00157                     }
    00158
    00159                     if (
    00160                         $token instanceof SgmlOpenTag
    00161                         && $token->getId() == 'meta'
    00162                         && $token->hasAttribute('content')
    00163                         && $token->hasAttribute('http-equiv')
    00164                         && mb_strtolower($token->getAttribute('http-equiv'))
    00165                             == self::HEADER_XRDS_LOCATION
    00166                     ) {
    00167                         $this->loadXRDS($token->getAttribute('content'));
    00168
    00169                         return $this;
    00170                     }
    00171                 }
    00172             }
    00173
    00174             return $this;
    00175         }
    00176
    00177         protected function parseXRDS($content)
    00178         {
    00179             if (preg_match('|<URI>(.*?)</URI>|uis', $content, $match)) {
    00180                 $this->server = HttpUrl::create()->parse($match[1]);
    00181             }
    00182
    00183             return $this;
    00184         }
    00185
    00186         protected function loadXRDS($url)
    00187         {
    00188             $response = $this->httpClient->send(
    00189                 HttpRequest::create()->
    00190                 setHeaderVar('Accept', self::HEADER_ACCEPT)->
    00191                 setMethod(HttpMethod::get())->
    00192                 setUrl(HttpUrl::create()->parse($url))
    00193             );
    00194
    00195             if ($response->getStatus()->getId() != 200) {
    00196                 throw new OpenIdException('can\'t fetch document');
    00197             }
    00198
    00199             $this->parseXRDS($response->getBody());
    00200
    00201             return $this;
    00202         }
    00203     }
    00204 ?>