1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49:
50: class LightOpenID
51: {
52: public $returnUrl
53: , $required = array()
54: , $optional = array()
55: , $verify_peer = null
56: , $capath = null
57: , $cainfo = null
58: , $data;
59: private $identity, $claimed_id;
60: protected $server, $version, $trustRoot, $aliases, $identifier_select = false
61: , $ax = false, $sreg = false, $setup_url = null, = array();
62: static protected $ax_to_sreg = array(
63: 'namePerson/friendly' => 'nickname',
64: 'contact/email' => 'email',
65: 'namePerson' => 'fullname',
66: 'birthDate' => 'dob',
67: 'person/gender' => 'gender',
68: 'contact/postalCode/home' => 'postcode',
69: 'contact/country/home' => 'country',
70: 'pref/language' => 'language',
71: 'pref/timezone' => 'timezone',
72: );
73:
74: function __construct($host)
75: {
76: $this->trustRoot = (strpos($host, '://') ? $host : 'http://' . $host);
77: if ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')
78: || (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
79: && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
80: ) {
81: $this->trustRoot = (strpos($host, '://') ? $host : 'https://' . $host);
82: }
83:
84: if(($host_end = strpos($this->trustRoot, '/', 8)) !== false) {
85: $this->trustRoot = substr($this->trustRoot, 0, $host_end);
86: }
87:
88: $uri = rtrim(preg_replace('#((?<=\?)|&)openid\.[^&]+#', '', $_SERVER['REQUEST_URI']), '?');
89: $this->returnUrl = $this->trustRoot . $uri;
90:
91: $this->data = ($_SERVER['REQUEST_METHOD'] === 'POST') ? $_POST : $_GET;
92:
93: if(!function_exists('curl_init') && !in_array('https', stream_get_wrappers())) {
94: throw new ErrorException('You must have either https wrappers or curl enabled.');
95: }
96: }
97:
98: function __set($name, $value)
99: {
100: switch ($name) {
101: case 'identity':
102: if (strlen($value = trim((String) $value))) {
103: if (preg_match('#^xri:/*#i', $value, $m)) {
104: $value = substr($value, strlen($m[0]));
105: } elseif (!preg_match('/^(?:[=@+\$!\(]|https?:)/i', $value)) {
106: $value = "http://$value";
107: }
108: if (preg_match('#^https?://[^/]+$#i', $value, $m)) {
109: $value .= '/';
110: }
111: }
112: $this->$name = $this->claimed_id = $value;
113: break;
114: case 'trustRoot':
115: case 'realm':
116: $this->trustRoot = trim($value);
117: }
118: }
119:
120: function __get($name)
121: {
122: switch ($name) {
123: case 'identity':
124:
125:
126:
127: return $this->claimed_id;
128: case 'trustRoot':
129: case 'realm':
130: return $this->trustRoot;
131: case 'mode':
132: return empty($this->data['openid_mode']) ? null : $this->data['openid_mode'];
133: }
134: }
135:
136: 137: 138: 139: 140: 141:
142: function hostExists($url)
143: {
144: if (strpos($url, '/') === false) {
145: $server = $url;
146: } else {
147: $server = @parse_url($url, PHP_URL_HOST);
148: }
149:
150: if (!$server) {
151: return false;
152: }
153:
154: return !!gethostbynamel($server);
155: }
156:
157: protected function request_curl($url, $method='GET', $params=array(), $update_claimed_id)
158: {
159: $params = http_build_query($params, '', '&');
160: $curl = curl_init($url . ($method == 'GET' && $params ? '?' . $params : ''));
161: curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
162: curl_setopt($curl, CURLOPT_HEADER, false);
163: curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
164: curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
165: curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/xrds+xml, */*'));
166:
167: if($this->verify_peer !== null) {
168: curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
169: if($this->capath) {
170: curl_setopt($curl, CURLOPT_CAPATH, $this->capath);
171: }
172:
173: if($this->cainfo) {
174: curl_setopt($curl, CURLOPT_CAINFO, $this->cainfo);
175: }
176: }
177:
178: if ($method == 'POST') {
179: curl_setopt($curl, CURLOPT_POST, true);
180: curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
181: } elseif ($method == 'HEAD') {
182: curl_setopt($curl, CURLOPT_HEADER, true);
183: curl_setopt($curl, CURLOPT_NOBODY, true);
184: } else {
185: curl_setopt($curl, CURLOPT_HEADER, true);
186: curl_setopt($curl, CURLOPT_HTTPGET, true);
187: }
188: $response = curl_exec($curl);
189:
190: if($method == 'HEAD' && curl_getinfo($curl, CURLINFO_HTTP_CODE) == 405) {
191: curl_setopt($curl, CURLOPT_HTTPGET, true);
192: $response = curl_exec($curl);
193: $response = substr($response, 0, strpos($response, "\r\n\r\n"));
194: }
195:
196: if($method == 'HEAD' || $method == 'GET') {
197: $header_response = $response;
198:
199:
200: if($method == 'GET') {
201: $header_response = substr($response, 0, strpos($response, "\r\n\r\n"));
202: }
203:
204: $headers = array();
205: foreach(explode("\n", $header_response) as $header) {
206: $pos = strpos($header,':');
207: if ($pos !== false) {
208: $name = strtolower(trim(substr($header, 0, $pos)));
209: $headers[$name] = trim(substr($header, $pos+1));
210: }
211: }
212:
213: if($update_claimed_id) {
214:
215: $effective_url = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);
216: if($effective_url != $url) {
217: $this->identity = $this->claimed_id = $effective_url;
218: }
219: }
220:
221: if($method == 'HEAD') {
222: return $headers;
223: } else {
224: $this->headers = $headers;
225: }
226: }
227:
228: if (curl_errno($curl)) {
229: throw new ErrorException(curl_error($curl), curl_errno($curl));
230: }
231:
232: return $response;
233: }
234:
235: protected function ($array, $update_claimed_id)
236: {
237: $headers = array();
238: foreach($array as $header) {
239: $pos = strpos($header,':');
240: if ($pos !== false) {
241: $name = strtolower(trim(substr($header, 0, $pos)));
242: $headers[$name] = trim(substr($header, $pos+1));
243:
244:
245:
246:
247:
248:
249: if($name == 'location' && $update_claimed_id) {
250: if(strpos($headers[$name], 'http') === 0) {
251: $this->identity = $this->claimed_id = $headers[$name];
252: } elseif($headers[$name][0] == '/') {
253: $parsed_url = parse_url($this->claimed_id);
254: $this->identity =
255: $this->claimed_id = $parsed_url['scheme'] . '://'
256: . $parsed_url['host']
257: . $headers[$name];
258: }
259: }
260: }
261: }
262: return $headers;
263: }
264:
265: protected function request_streams($url, $method='GET', $params=array(), $update_claimed_id)
266: {
267: if(!$this->hostExists($url)) {
268: throw new ErrorException("Could not connect to $url.", 404);
269: }
270:
271: $params = http_build_query($params, '', '&');
272: switch($method) {
273: case 'GET':
274: $opts = array(
275: 'http' => array(
276: 'method' => 'GET',
277: 'header' => 'Accept: application/xrds+xml, */*',
278: 'ignore_errors' => true,
279: ), 'ssl' => array(
280: 'CN_match' => parse_url($url, PHP_URL_HOST),
281: ),
282: );
283: $url = $url . ($params ? '?' . $params : '');
284: break;
285: case 'POST':
286: $opts = array(
287: 'http' => array(
288: 'method' => 'POST',
289: 'header' => 'Content-type: application/x-www-form-urlencoded',
290: 'content' => $params,
291: 'ignore_errors' => true,
292: ), 'ssl' => array(
293: 'CN_match' => parse_url($url, PHP_URL_HOST),
294: ),
295: );
296: break;
297: case 'HEAD':
298:
299:
300:
301: $default = stream_context_get_options(stream_context_get_default());
302: stream_context_get_default(
303: array(
304: 'http' => array(
305: 'method' => 'HEAD',
306: 'header' => 'Accept: application/xrds+xml, */*',
307: 'ignore_errors' => true,
308: ), 'ssl' => array(
309: 'CN_match' => parse_url($url, PHP_URL_HOST),
310: ),
311: )
312: );
313:
314: $url = $url . ($params ? '?' . $params : '');
315: $headers = get_headers ($url);
316: if(!$headers) {
317: return array();
318: }
319:
320: if(intval(substr($headers[0], strlen('HTTP/1.1 '))) == 405) {
321:
322:
323: $args = func_get_args();
324: $args[1] = 'GET';
325: call_user_func_array(array($this, 'request_streams'), $args);
326: return $this->headers;
327: }
328:
329: $headers = $this->parse_header_array($headers, $update_claimed_id);
330:
331:
332: stream_context_get_default($default);
333: return $headers;
334: }
335:
336: if($this->verify_peer) {
337: $opts['ssl'] += array(
338: 'verify_peer' => true,
339: 'capath' => $this->capath,
340: 'cafile' => $this->cainfo,
341: );
342: }
343:
344: $context = stream_context_create ($opts);
345: $data = file_get_contents($url, false, $context);
346:
347:
348: if(isset($http_response_header)) {
349: $this->headers = $this->parse_header_array($http_response_header, $update_claimed_id);
350: }
351:
352: return file_get_contents($url, false, $context);
353: }
354:
355: protected function request($url, $method='GET', $params=array(), $update_claimed_id=false)
356: {
357: if (function_exists('curl_init')
358: && (!in_array('https', stream_get_wrappers()) || !ini_get('safe_mode') && !ini_get('open_basedir'))
359: ) {
360: return $this->request_curl($url, $method, $params, $update_claimed_id);
361: }
362: return $this->request_streams($url, $method, $params, $update_claimed_id);
363: }
364:
365: protected function build_url($url, $parts)
366: {
367: if (isset($url['query'], $parts['query'])) {
368: $parts['query'] = $url['query'] . '&' . $parts['query'];
369: }
370:
371: $url = $parts + $url;
372: $url = $url['scheme'] . '://'
373: . (empty($url['username'])?''
374: :(empty($url['password'])? "{$url['username']}@"
375: :"{$url['username']}:{$url['password']}@"))
376: . $url['host']
377: . (empty($url['port'])?'':":{$url['port']}")
378: . (empty($url['path'])?'':$url['path'])
379: . (empty($url['query'])?'':"?{$url['query']}")
380: . (empty($url['fragment'])?'':"#{$url['fragment']}");
381: return $url;
382: }
383:
384: 385: 386: 387:
388: protected function htmlTag($content, $tag, $attrName, $attrValue, $valueName)
389: {
390: preg_match_all("#<{$tag}[^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*$valueName=['\"](.+?)['\"][^>]*/?>#i", $content, $matches1);
391: preg_match_all("#<{$tag}[^>]*$valueName=['\"](.+?)['\"][^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*/?>#i", $content, $matches2);
392:
393: $result = array_merge($matches1[1], $matches2[1]);
394: return empty($result)?false:$result[0];
395: }
396:
397: 398: 399: 400: 401: 402:
403: function discover($url)
404: {
405: if (!$url) throw new ErrorException('No identity supplied.');
406:
407: if (!preg_match('#^https?:#', $url)) {
408: $url = "https://xri.net/$url";
409: }
410:
411:
412:
413:
414: $originalUrl = $url;
415:
416:
417: $yadis = true;
418:
419:
420: for ($i = 0; $i < 5; $i ++) {
421: if ($yadis) {
422: $headers = $this->request($url, 'HEAD', array(), true);
423:
424: $next = false;
425: if (isset($headers['x-xrds-location'])) {
426: $url = $this->build_url(parse_url($url), parse_url(trim($headers['x-xrds-location'])));
427: $next = true;
428: }
429:
430: if (isset($headers['content-type'])
431: && (strpos($headers['content-type'], 'application/xrds+xml') !== false
432: || strpos($headers['content-type'], 'text/xml') !== false)
433: ) {
434:
435:
436:
437:
438:
439: $content = $this->request($url, 'GET');
440:
441: preg_match_all('#<Service.*?>(.*?)</Service>#s', $content, $m);
442: foreach($m[1] as $content) {
443: $content = ' ' . $content;
444:
445:
446: $ns = preg_quote('http://specs.openid.net/auth/2.0/', '#');
447: if(preg_match('#<Type>\s*'.$ns.'(server|signon)\s*</Type>#s', $content, $type)) {
448: if ($type[1] == 'server') $this->identifier_select = true;
449:
450: preg_match('#<URI.*?>(.*)</URI>#', $content, $server);
451: preg_match('#<(Local|Canonical)ID>(.*)</\1ID>#', $content, $delegate);
452: if (empty($server)) {
453: return false;
454: }
455:
456: $this->ax = (bool) strpos($content, '<Type>http://openid.net/srv/ax/1.0</Type>');
457: $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>')
458: || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>');
459:
460: $server = $server[1];
461: if (isset($delegate[2])) $this->identity = trim($delegate[2]);
462: $this->version = 2;
463:
464: $this->server = $server;
465: return $server;
466: }
467:
468:
469: $ns = preg_quote('http://openid.net/signon/1.1', '#');
470: if (preg_match('#<Type>\s*'.$ns.'\s*</Type>#s', $content)) {
471:
472: preg_match('#<URI.*?>(.*)</URI>#', $content, $server);
473: preg_match('#<.*?Delegate>(.*)</.*?Delegate>#', $content, $delegate);
474: if (empty($server)) {
475: return false;
476: }
477:
478: $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>')
479: || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>');
480:
481: $server = $server[1];
482: if (isset($delegate[1])) $this->identity = $delegate[1];
483: $this->version = 1;
484:
485: $this->server = $server;
486: return $server;
487: }
488: }
489:
490: $next = true;
491: $yadis = false;
492: $url = $originalUrl;
493: $content = null;
494: break;
495: }
496: if ($next) continue;
497:
498:
499: $content = $this->request($url, 'GET', array(), true);
500:
501: if (isset($this->headers['x-xrds-location'])) {
502: $url = $this->build_url(parse_url($url), parse_url(trim($this->headers['x-xrds-location'])));
503: continue;
504: }
505:
506: $location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'content');
507: if ($location) {
508: $url = $this->build_url(parse_url($url), parse_url($location));
509: continue;
510: }
511: }
512:
513: if (!$content) $content = $this->request($url, 'GET');
514:
515:
516:
517: $server = $this->htmlTag($content, 'link', 'rel', 'openid2.provider', 'href');
518: $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_id', 'href');
519: $this->version = 2;
520:
521: if (!$server) {
522:
523: $server = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href');
524: $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href');
525: $this->version = 1;
526: }
527:
528: if ($server) {
529:
530: if ($delegate) {
531:
532: $this->identity = $delegate;
533: }
534: $this->server = $server;
535: return $server;
536: }
537:
538: throw new ErrorException("No OpenID Server found at $url", 404);
539: }
540: throw new ErrorException('Endless redirection!', 500);
541: }
542:
543: protected function sregParams()
544: {
545: $params = array();
546:
547:
548:
549: $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1';
550: if ($this->required) {
551: $params['openid.sreg.required'] = array();
552: foreach ($this->required as $required) {
553: if (!isset(self::$ax_to_sreg[$required])) continue;
554: $params['openid.sreg.required'][] = self::$ax_to_sreg[$required];
555: }
556: $params['openid.sreg.required'] = implode(',', $params['openid.sreg.required']);
557: }
558:
559: if ($this->optional) {
560: $params['openid.sreg.optional'] = array();
561: foreach ($this->optional as $optional) {
562: if (!isset(self::$ax_to_sreg[$optional])) continue;
563: $params['openid.sreg.optional'][] = self::$ax_to_sreg[$optional];
564: }
565: $params['openid.sreg.optional'] = implode(',', $params['openid.sreg.optional']);
566: }
567: return $params;
568: }
569:
570: protected function axParams()
571: {
572: $params = array();
573: if ($this->required || $this->optional) {
574: $params['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0';
575: $params['openid.ax.mode'] = 'fetch_request';
576: $this->aliases = array();
577: $counts = array();
578: $required = array();
579: $optional = array();
580: foreach (array('required','optional') as $type) {
581: foreach ($this->$type as $alias => $field) {
582: if (is_int($alias)) $alias = strtr($field, '/', '_');
583: $this->aliases[$alias] = 'http://axschema.org/' . $field;
584: if (empty($counts[$alias])) $counts[$alias] = 0;
585: $counts[$alias] += 1;
586: ${$type}[] = $alias;
587: }
588: }
589: foreach ($this->aliases as $alias => $ns) {
590: $params['openid.ax.type.' . $alias] = $ns;
591: }
592: foreach ($counts as $alias => $count) {
593: if ($count == 1) continue;
594: $params['openid.ax.count.' . $alias] = $count;
595: }
596:
597:
598:
599: if($required) {
600: $params['openid.ax.required'] = implode(',', $required);
601: }
602: if($optional) {
603: $params['openid.ax.if_available'] = implode(',', $optional);
604: }
605: }
606: return $params;
607: }
608:
609: protected function authUrl_v1($immediate)
610: {
611: $returnUrl = $this->returnUrl;
612:
613:
614:
615: if($this->identity != $this->claimed_id) {
616: $returnUrl .= (strpos($returnUrl, '?') ? '&' : '?') . 'openid.claimed_id=' . $this->claimed_id;
617: }
618:
619: $params = array(
620: 'openid.return_to' => $returnUrl,
621: 'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
622: 'openid.identity' => $this->identity,
623: 'openid.trust_root' => $this->trustRoot,
624: ) + $this->sregParams();
625:
626: return $this->build_url(parse_url($this->server)
627: , array('query' => http_build_query($params, '', '&')));
628: }
629:
630: protected function authUrl_v2($immediate)
631: {
632: $params = array(
633: 'openid.ns' => 'http://specs.openid.net/auth/2.0',
634: 'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
635: 'openid.return_to' => $this->returnUrl,
636: 'openid.realm' => $this->trustRoot,
637: );
638: if ($this->ax) {
639: $params += $this->axParams();
640: }
641: if ($this->sreg) {
642: $params += $this->sregParams();
643: }
644: if (!$this->ax && !$this->sreg) {
645:
646:
647: $params += $this->axParams() + $this->sregParams();
648: }
649:
650: if ($this->identifier_select) {
651: $params['openid.identity'] = $params['openid.claimed_id']
652: = 'http://specs.openid.net/auth/2.0/identifier_select';
653: } else {
654: $params['openid.identity'] = $this->identity;
655: $params['openid.claimed_id'] = $this->claimed_id;
656: }
657:
658: return $this->build_url(parse_url($this->server)
659: , array('query' => http_build_query($params, '', '&')));
660: }
661:
662: 663: 664: 665: 666: 667:
668: function authUrl($immediate = false)
669: {
670: if ($this->setup_url && !$immediate) return $this->setup_url;
671: if (!$this->server) $this->discover($this->identity);
672:
673: if ($this->version == 2) {
674: return $this->authUrl_v2($immediate);
675: }
676: return $this->authUrl_v1($immediate);
677: }
678:
679: 680: 681: 682: 683:
684: function validate()
685: {
686:
687:
688:
689:
690: if(isset($this->data['openid_user_setup_url'])) {
691: $this->setup_url = $this->data['openid_user_setup_url'];
692: return false;
693: }
694: if($this->mode != 'id_res') {
695: return false;
696: }
697:
698: $this->claimed_id = isset($this->data['openid_claimed_id'])?$this->data['openid_claimed_id']:$this->data['openid_identity'];
699: $params = array(
700: 'openid.assoc_handle' => $this->data['openid_assoc_handle'],
701: 'openid.signed' => $this->data['openid_signed'],
702: 'openid.sig' => $this->data['openid_sig'],
703: );
704:
705: if (isset($this->data['openid_ns'])) {
706:
707:
708:
709: $params['openid.ns'] = 'http://specs.openid.net/auth/2.0';
710: } elseif (isset($this->data['openid_claimed_id'])
711: && $this->data['openid_claimed_id'] != $this->data['openid_identity']
712: ) {
713:
714:
715: $this->returnUrl .= (strpos($this->returnUrl, '?') ? '&' : '?')
716: . 'openid.claimed_id=' . $this->claimed_id;
717: }
718:
719: if ($this->data['openid_return_to'] != $this->returnUrl) {
720:
721:
722: return false;
723: }
724:
725: $server = $this->discover($this->claimed_id);
726:
727: foreach (explode(',', $this->data['openid_signed']) as $item) {
728:
729:
730:
731:
732:
733:
734: $value = $this->data['openid_' . str_replace('.','_',$item)];
735: $params['openid.' . $item] = function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc() ? stripslashes($value) : $value;
736:
737: }
738:
739: $params['openid.mode'] = 'check_authentication';
740:
741: $response = $this->request($server, 'POST', $params);
742:
743: return preg_match('/is_valid\s*:\s*true/i', $response);
744: }
745:
746: protected function getAxAttributes()
747: {
748: $alias = null;
749: if (isset($this->data['openid_ns_ax'])
750: && $this->data['openid_ns_ax'] != 'http://openid.net/srv/ax/1.0'
751: ) {
752: $alias = 'ax';
753: } else {
754:
755:
756: foreach ($this->data as $key => $val) {
757: if (substr($key, 0, strlen('openid_ns_')) == 'openid_ns_'
758: && $val == 'http://openid.net/srv/ax/1.0'
759: ) {
760: $alias = substr($key, strlen('openid_ns_'));
761: break;
762: }
763: }
764: }
765: if (!$alias) {
766:
767:
768: return array();
769: }
770:
771: $attributes = array();
772: foreach (explode(',', $this->data['openid_signed']) as $key) {
773: $keyMatch = $alias . '.value.';
774: if (substr($key, 0, strlen($keyMatch)) != $keyMatch) {
775: continue;
776: }
777: $key = substr($key, strlen($keyMatch));
778: if (!isset($this->data['openid_' . $alias . '_type_' . $key])) {
779:
780:
781:
782: continue;
783: }
784: $value = $this->data['openid_' . $alias . '_value_' . $key];
785: $key = substr($this->data['openid_' . $alias . '_type_' . $key],
786: strlen('http://axschema.org/'));
787:
788: $attributes[$key] = $value;
789: }
790: return $attributes;
791: }
792:
793: protected function getSregAttributes()
794: {
795: $attributes = array();
796: $sreg_to_ax = array_flip(self::$ax_to_sreg);
797: foreach (explode(',', $this->data['openid_signed']) as $key) {
798: $keyMatch = 'sreg.';
799: if (substr($key, 0, strlen($keyMatch)) != $keyMatch) {
800: continue;
801: }
802: $key = substr($key, strlen($keyMatch));
803: if (!isset($sreg_to_ax[$key])) {
804:
805: continue;
806: }
807: $attributes[$sreg_to_ax[$key]] = $this->data['openid_sreg_' . $key];
808: }
809: return $attributes;
810: }
811:
812: 813: 814: 815: 816: 817: 818: 819: 820:
821: function getAttributes()
822: {
823: if (isset($this->data['openid_ns'])
824: && $this->data['openid_ns'] == 'http://specs.openid.net/auth/2.0'
825: ) {
826:
827: return $this->getAxAttributes() + $this->getSregAttributes();
828: }
829: return $this->getSregAttributes();
830: }
831: }
832: