Go to the documentation of this file.00001 <?php
00002
00003
00004
00005
00006
00007
00008
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 ?>