This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * This class provides a simple interface for OpenID (1.1 and 2.0) authentication. |
||
4 | * Supports Yadis discovery. |
||
5 | * The authentication process is stateless/dumb. |
||
6 | * |
||
7 | * Usage: |
||
8 | * Sign-on with OpenID is a two step process: |
||
9 | * Step one is authentication with the provider: |
||
10 | * <code> |
||
11 | * $openid = new LightOpenID('my-host.example.org'); |
||
12 | * $openid->identity = 'ID supplied by user'; |
||
13 | * header('Location: ' . $openid->authUrl()); |
||
14 | * </code> |
||
15 | * The provider then sends various parameters via GET, one of them is openid_mode. |
||
16 | * Step two is verification: |
||
17 | * <code> |
||
18 | * $openid = new LightOpenID('my-host.example.org'); |
||
19 | * if ($openid->mode) { |
||
20 | * echo $openid->validate() ? 'Logged in.' : 'Failed'; |
||
21 | * } |
||
22 | * </code> |
||
23 | * |
||
24 | * Change the 'my-host.example.org' to your domain name. Do NOT use $_SERVER['HTTP_HOST'] |
||
25 | * for that, unless you know what you are doing. |
||
26 | * |
||
27 | * Optionally, you can set $returnUrl and $realm (or $trustRoot, which is an alias). |
||
28 | * The default values for those are: |
||
29 | * $openid->realm = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST']; |
||
30 | * $openid->returnUrl = $openid->realm . $_SERVER['REQUEST_URI']; |
||
31 | * If you don't know their meaning, refer to any openid tutorial, or specification. Or just guess. |
||
32 | * |
||
33 | * AX and SREG extensions are supported. |
||
34 | * To use them, specify $openid->required and/or $openid->optional before calling $openid->authUrl(). |
||
35 | * These are arrays, with values being AX schema paths (the 'path' part of the URL). |
||
36 | * For example: |
||
37 | * $openid->required = array('namePerson/friendly', 'contact/email'); |
||
38 | * $openid->optional = array('namePerson/first'); |
||
39 | * If the server supports only SREG or OpenID 1.1, these are automaticaly |
||
40 | * mapped to SREG names, so that user doesn't have to know anything about the server. |
||
41 | * |
||
42 | * To get the values, use $openid->getAttributes(). |
||
43 | * |
||
44 | * |
||
45 | * The library requires PHP >= 5.1.2 with curl or http/https stream wrappers enabled. |
||
46 | * @author Mewp |
||
47 | * @copyright Copyright (c) 2010, Mewp |
||
48 | * @license http://www.opensource.org/licenses/mit-license.php MIT |
||
49 | */ |
||
50 | class LightOpenID |
||
0 ignored issues
–
show
|
|||
51 | { |
||
52 | public $returnUrl |
||
0 ignored issues
–
show
|
|||
53 | , $required = array() |
||
54 | , $optional = array() |
||
55 | , $verify_peer = null |
||
56 | , $capath = null |
||
57 | , $cainfo = null |
||
58 | , $data; |
||
59 | private $identity, $claimed_id; |
||
0 ignored issues
–
show
|
|||
60 | protected $server, $version, $trustRoot, $aliases, $identifier_select = false |
||
0 ignored issues
–
show
|
|||
61 | , $ax = false, $sreg = false, $setup_url = null, $headers = array(); |
||
0 ignored issues
–
show
|
|||
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) |
||
0 ignored issues
–
show
|
|||
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) |
||
0 ignored issues
–
show
|
|||
99 | { |
||
100 | switch ($name) { |
||
101 | case 'identity': |
||
102 | if (strlen($value = trim((String) $value))) { |
||
103 | if (preg_match('#^xri:/*#i', $value, $m)) { |
||
0 ignored issues
–
show
|
|||
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) |
||
0 ignored issues
–
show
|
|||
121 | { |
||
122 | switch ($name) { |
||
123 | case 'identity': |
||
124 | # We return claimed_id instead of identity, |
||
0 ignored issues
–
show
|
|||
125 | # because the developer should see the claimed identifier, |
||
0 ignored issues
–
show
|
|||
126 | # i.e. what he set as identity, not the op-local identifier (which is what we verify) |
||
0 ignored issues
–
show
|
|||
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 | * Checks if the server specified in the url exists. |
||
138 | * |
||
139 | * @param $url url to check |
||
140 | * @return true, if the server exists; false otherwise |
||
0 ignored issues
–
show
The doc-type
true, could not be parsed: Expected "|" or "end of type", but got "," at position 4. (view supported doc-types)
This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types. ![]() |
|||
141 | */ |
||
142 | function hostExists($url) |
||
0 ignored issues
–
show
|
|||
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 | # If it's a GET request, we want to only parse the header part. |
||
0 ignored issues
–
show
|
|||
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 | # Updating claimed_id in case of redirections. |
||
0 ignored issues
–
show
|
|||
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 parse_header_array($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 | # Following possible redirections. The point is just to have |
||
0 ignored issues
–
show
|
|||
245 | # claimed_id change with them, because the redirections |
||
0 ignored issues
–
show
|
|||
246 | # are followed automatically. |
||
0 ignored issues
–
show
|
|||
247 | # We ignore redirections with relative paths. |
||
0 ignored issues
–
show
|
|||
248 | # If any known provider uses them, file a bug report. |
||
0 ignored issues
–
show
|
|||
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 | # We want to send a HEAD request, |
||
0 ignored issues
–
show
|
|||
299 | # but since get_headers doesn't accept $context parameter, |
||
0 ignored issues
–
show
|
|||
300 | # we have to change the defaults. |
||
0 ignored issues
–
show
|
|||
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) { |
||
0 ignored issues
–
show
The expression
$headers of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
317 | return array(); |
||
318 | } |
||
319 | |||
320 | if (intval(substr($headers[0], strlen('HTTP/1.1 '))) == 405) { |
||
321 | # The server doesn't support HEAD, so let's emulate it with |
||
0 ignored issues
–
show
|
|||
322 | # a GET. |
||
0 ignored issues
–
show
|
|||
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 | # And restore them. |
||
0 ignored issues
–
show
|
|||
332 | stream_context_get_default($default); |
||
333 | return $headers; |
||
334 | } |
||
335 | |||
336 | if ($this->verify_peer) { |
||
337 | $opts['ssl'] += array( |
||
0 ignored issues
–
show
The variable
$opts does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
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 | # This is a hack for providers who don't support HEAD requests. |
||
0 ignored issues
–
show
|
|||
347 | # It just creates the headers array for the last request in $this->headers. |
||
0 ignored issues
–
show
|
|||
348 | if (isset($http_response_header)) { |
||
349 | $this->headers = $this->parse_header_array($http_response_header, $update_claimed_id); |
||
350 | } |
||
351 | |||
352 | return $data; |
||
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 | * Helper function used to scan for <meta>/<link> tags and extract information |
||
386 | * from them |
||
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 | * Performs Yadis and HTML discovery. Normally not used. |
||
399 | * @param $url Identity URL. |
||
400 | * @return String OP Endpoint (i.e. OpenID provider address). |
||
401 | * @throws ErrorException |
||
402 | */ |
||
403 | function discover($url) |
||
0 ignored issues
–
show
|
|||
404 | { |
||
405 | if (!$url) { |
||
406 | throw new ErrorException('No identity supplied.'); |
||
407 | } |
||
408 | # Use xri.net proxy to resolve i-name identities |
||
0 ignored issues
–
show
|
|||
409 | if (!preg_match('#^https?:#', $url)) { |
||
410 | $url = "https://xri.net/$url"; |
||
411 | } |
||
412 | |||
413 | # We save the original url in case of Yadis discovery failure. |
||
0 ignored issues
–
show
|
|||
414 | # It can happen when we'll be lead to an XRDS document |
||
0 ignored issues
–
show
|
|||
415 | # which does not have any OpenID2 services. |
||
0 ignored issues
–
show
|
|||
416 | $originalUrl = $url; |
||
417 | |||
418 | # A flag to disable yadis discovery in case of failure in headers. |
||
0 ignored issues
–
show
|
|||
419 | $yadis = true; |
||
420 | |||
421 | # We'll jump a maximum of 5 times, to avoid endless redirections. |
||
0 ignored issues
–
show
|
|||
422 | for ($i = 0; $i < 5; $i++) { |
||
423 | if ($yadis) { |
||
424 | $headers = $this->request($url, 'HEAD', array(), true); |
||
425 | |||
426 | $next = false; |
||
427 | if (isset($headers['x-xrds-location'])) { |
||
428 | $url = $this->build_url(parse_url($url), parse_url(trim($headers['x-xrds-location']))); |
||
429 | $next = true; |
||
430 | } |
||
431 | |||
432 | if (isset($headers['content-type']) |
||
433 | && (strpos($headers['content-type'], 'application/xrds+xml') !== false |
||
434 | || strpos($headers['content-type'], 'text/xml') !== false) |
||
435 | ) { |
||
436 | # Apparently, some providers return XRDS documents as text/html. |
||
0 ignored issues
–
show
|
|||
437 | # While it is against the spec, allowing this here shouldn't break |
||
0 ignored issues
–
show
|
|||
438 | # compatibility with anything. |
||
0 ignored issues
–
show
|
|||
439 | # --- |
||
0 ignored issues
–
show
|
|||
440 | # Found an XRDS document, now let's find the server, and optionally delegate. |
||
0 ignored issues
–
show
|
|||
441 | $content = $this->request($url, 'GET'); |
||
442 | |||
443 | preg_match_all('#<Service.*?>(.*?)</Service>#s', $content, $m); |
||
0 ignored issues
–
show
|
|||
444 | foreach ($m[1] as $content) { |
||
445 | $content = ' ' . $content; # The space is added, so that strpos doesn't return 0. |
||
0 ignored issues
–
show
|
|||
446 | |||
447 | # OpenID 2 |
||
0 ignored issues
–
show
|
|||
448 | $ns = preg_quote('http://specs.openid.net/auth/2.0/', '#'); |
||
449 | if (preg_match('#<Type>\s*' . $ns . '(server|signon)\s*</Type>#s', $content, $type)) { |
||
450 | if ($type[1] == 'server') { |
||
451 | $this->identifier_select = true; |
||
452 | } |
||
453 | |||
454 | preg_match('#<URI.*?>(.*)</URI>#', $content, $server); |
||
455 | preg_match('#<(Local|Canonical)ID>(.*)</\1ID>#', $content, $delegate); |
||
456 | if (empty($server)) { |
||
457 | return false; |
||
0 ignored issues
–
show
The return type of
return false; (false ) is incompatible with the return type documented by LightOpenID::discover of type string .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
458 | } |
||
459 | # Does the server advertise support for either AX or SREG? |
||
0 ignored issues
–
show
|
|||
460 | $this->ax = (bool) strpos($content, '<Type>http://openid.net/srv/ax/1.0</Type>'); |
||
461 | $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>') |
||
462 | || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>'); |
||
463 | |||
464 | $server = $server[1]; |
||
465 | if (isset($delegate[2])) { |
||
466 | $this->identity = trim($delegate[2]); |
||
467 | } |
||
468 | $this->version = 2; |
||
469 | |||
470 | $this->server = $server; |
||
471 | return $server; |
||
472 | } |
||
473 | |||
474 | # OpenID 1.1 |
||
0 ignored issues
–
show
|
|||
475 | $ns = preg_quote('http://openid.net/signon/1.1', '#'); |
||
476 | if (preg_match('#<Type>\s*' . $ns . '\s*</Type>#s', $content)) { |
||
477 | |||
478 | preg_match('#<URI.*?>(.*)</URI>#', $content, $server); |
||
479 | preg_match('#<.*?Delegate>(.*)</.*?Delegate>#', $content, $delegate); |
||
480 | if (empty($server)) { |
||
481 | return false; |
||
0 ignored issues
–
show
The return type of
return false; (false ) is incompatible with the return type documented by LightOpenID::discover of type string .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
482 | } |
||
483 | # AX can be used only with OpenID 2.0, so checking only SREG |
||
0 ignored issues
–
show
|
|||
484 | $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>') |
||
485 | || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>'); |
||
486 | |||
487 | $server = $server[1]; |
||
488 | if (isset($delegate[1])) { |
||
489 | $this->identity = $delegate[1]; |
||
490 | } |
||
491 | $this->version = 1; |
||
492 | |||
493 | $this->server = $server; |
||
494 | return $server; |
||
495 | } |
||
496 | } |
||
497 | |||
498 | $next = true; |
||
0 ignored issues
–
show
$next is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
499 | $yadis = false; |
||
0 ignored issues
–
show
$yadis is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
500 | $url = $originalUrl; |
||
0 ignored issues
–
show
$url is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
501 | $content = null; |
||
0 ignored issues
–
show
$content is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
502 | break; |
||
503 | } |
||
504 | if ($next) { |
||
505 | continue; |
||
506 | } |
||
507 | |||
508 | # There are no relevant information in headers, so we search the body. |
||
0 ignored issues
–
show
|
|||
509 | $content = $this->request($url, 'GET', array(), true); |
||
510 | |||
511 | if (isset($this->headers['x-xrds-location'])) { |
||
512 | $url = $this->build_url(parse_url($url), parse_url(trim($this->headers['x-xrds-location']))); |
||
513 | continue; |
||
514 | } |
||
515 | |||
516 | $location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'content'); |
||
517 | if ($location) { |
||
518 | $url = $this->build_url(parse_url($url), parse_url($location)); |
||
519 | continue; |
||
520 | } |
||
521 | } |
||
522 | |||
523 | if (!$content) { |
||
0 ignored issues
–
show
The variable
$content does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
524 | $content = $this->request($url, 'GET'); |
||
525 | } |
||
526 | |||
527 | # At this point, the YADIS Discovery has failed, so we'll switch |
||
0 ignored issues
–
show
|
|||
528 | # to openid2 HTML discovery, then fallback to openid 1.1 discovery. |
||
0 ignored issues
–
show
|
|||
529 | $server = $this->htmlTag($content, 'link', 'rel', 'openid2.provider', 'href'); |
||
530 | $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_id', 'href'); |
||
531 | $this->version = 2; |
||
532 | |||
533 | if (!$server) { |
||
534 | # The same with openid 1.1 |
||
0 ignored issues
–
show
|
|||
535 | $server = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href'); |
||
536 | $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href'); |
||
537 | $this->version = 1; |
||
538 | } |
||
539 | |||
540 | if ($server) { |
||
541 | # We found an OpenID2 OP Endpoint |
||
0 ignored issues
–
show
|
|||
542 | if ($delegate) { |
||
543 | # We have also found an OP-Local ID. |
||
0 ignored issues
–
show
|
|||
544 | $this->identity = $delegate; |
||
545 | } |
||
546 | $this->server = $server; |
||
547 | return $server; |
||
548 | } |
||
549 | |||
550 | throw new ErrorException("No OpenID Server found at $url", 404); |
||
551 | } |
||
552 | throw new ErrorException('Endless redirection!', 500); |
||
553 | } |
||
554 | |||
555 | protected function sregParams() |
||
556 | { |
||
557 | $params = array(); |
||
558 | # We always use SREG 1.1, even if the server is advertising only support for 1.0. |
||
0 ignored issues
–
show
|
|||
559 | # That's because it's fully backwards compatibile with 1.0, and some providers |
||
0 ignored issues
–
show
|
|||
560 | # advertise 1.0 even if they accept only 1.1. One such provider is myopenid.com |
||
0 ignored issues
–
show
|
|||
561 | $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1'; |
||
562 | View Code Duplication | if ($this->required) { |
|
0 ignored issues
–
show
The expression
$this->required of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
563 | $params['openid.sreg.required'] = array(); |
||
564 | foreach ($this->required as $required) { |
||
565 | if (!isset(self::$ax_to_sreg[$required])) { |
||
566 | continue; |
||
567 | } |
||
568 | $params['openid.sreg.required'][] = self::$ax_to_sreg[$required]; |
||
569 | } |
||
570 | $params['openid.sreg.required'] = implode(',', $params['openid.sreg.required']); |
||
571 | } |
||
572 | |||
573 | View Code Duplication | if ($this->optional) { |
|
0 ignored issues
–
show
The expression
$this->optional of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
574 | $params['openid.sreg.optional'] = array(); |
||
575 | foreach ($this->optional as $optional) { |
||
576 | if (!isset(self::$ax_to_sreg[$optional])) { |
||
577 | continue; |
||
578 | } |
||
579 | $params['openid.sreg.optional'][] = self::$ax_to_sreg[$optional]; |
||
580 | } |
||
581 | $params['openid.sreg.optional'] = implode(',', $params['openid.sreg.optional']); |
||
582 | } |
||
583 | return $params; |
||
584 | } |
||
585 | |||
586 | protected function axParams() |
||
587 | { |
||
588 | $params = array(); |
||
589 | if ($this->required || $this->optional) { |
||
0 ignored issues
–
show
The expression
$this->required of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() The expression
$this->optional of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
590 | $params['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0'; |
||
591 | $params['openid.ax.mode'] = 'fetch_request'; |
||
592 | $this->aliases = array(); |
||
593 | $counts = array(); |
||
594 | $required = array(); |
||
595 | $optional = array(); |
||
596 | foreach (array('required', 'optional') as $type) { |
||
597 | foreach ($this->$type as $alias => $field) { |
||
598 | if (is_int($alias)) { |
||
599 | $alias = strtr($field, '/', '_'); |
||
600 | } |
||
601 | $this->aliases[$alias] = 'http://axschema.org/' . $field; |
||
602 | if (empty($counts[$alias])) { |
||
603 | $counts[$alias] = 0; |
||
604 | } |
||
605 | $counts[$alias] += 1; |
||
606 | ${$type}[] = $alias; |
||
607 | } |
||
608 | } |
||
609 | foreach ($this->aliases as $alias => $ns) { |
||
610 | $params['openid.ax.type.' . $alias] = $ns; |
||
611 | } |
||
612 | foreach ($counts as $alias => $count) { |
||
613 | if ($count == 1) { |
||
614 | continue; |
||
615 | } |
||
616 | $params['openid.ax.count.' . $alias] = $count; |
||
617 | } |
||
618 | |||
619 | # Don't send empty ax.requied and ax.if_available. |
||
0 ignored issues
–
show
|
|||
620 | # Google and possibly other providers refuse to support ax when one of these is empty. |
||
0 ignored issues
–
show
|
|||
621 | if ($required) { |
||
0 ignored issues
–
show
The expression
$required of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
622 | $params['openid.ax.required'] = implode(',', $required); |
||
623 | } |
||
624 | if ($optional) { |
||
0 ignored issues
–
show
The expression
$optional of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
625 | $params['openid.ax.if_available'] = implode(',', $optional); |
||
626 | } |
||
627 | } |
||
628 | return $params; |
||
629 | } |
||
630 | |||
631 | protected function authUrl_v1($immediate) |
||
632 | { |
||
633 | $returnUrl = $this->returnUrl; |
||
634 | # If we have an openid.delegate that is different from our claimed id, |
||
0 ignored issues
–
show
|
|||
635 | # we need to somehow preserve the claimed id between requests. |
||
0 ignored issues
–
show
|
|||
636 | # The simplest way is to just send it along with the return_to url. |
||
0 ignored issues
–
show
|
|||
637 | if ($this->identity != $this->claimed_id) { |
||
638 | $returnUrl .= (strpos($returnUrl, '?') ? '&' : '?') . 'openid.claimed_id=' . $this->claimed_id; |
||
639 | } |
||
640 | |||
641 | $params = array( |
||
642 | 'openid.return_to' => $returnUrl, |
||
643 | 'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup', |
||
644 | 'openid.identity' => $this->identity, |
||
645 | 'openid.trust_root' => $this->trustRoot, |
||
646 | ) + $this->sregParams(); |
||
647 | |||
648 | return $this->build_url(parse_url($this->server) |
||
649 | , array('query' => http_build_query($params, '', '&'))); |
||
650 | } |
||
651 | |||
652 | protected function authUrl_v2($immediate) |
||
653 | { |
||
654 | $params = array( |
||
655 | 'openid.ns' => 'http://specs.openid.net/auth/2.0', |
||
656 | 'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup', |
||
657 | 'openid.return_to' => $this->returnUrl, |
||
658 | 'openid.realm' => $this->trustRoot, |
||
659 | ); |
||
660 | if ($this->ax) { |
||
661 | $params += $this->axParams(); |
||
662 | } |
||
663 | if ($this->sreg) { |
||
664 | $params += $this->sregParams(); |
||
665 | } |
||
666 | if (!$this->ax && !$this->sreg) { |
||
667 | # If OP doesn't advertise either SREG, nor AX, let's send them both |
||
0 ignored issues
–
show
|
|||
668 | # in worst case we don't get anything in return. |
||
0 ignored issues
–
show
|
|||
669 | $params += $this->axParams() + $this->sregParams(); |
||
670 | } |
||
671 | |||
672 | if ($this->identifier_select) { |
||
673 | $params['openid.identity'] = $params['openid.claimed_id'] |
||
674 | = 'http://specs.openid.net/auth/2.0/identifier_select'; |
||
675 | } else { |
||
676 | $params['openid.identity'] = $this->identity; |
||
677 | $params['openid.claimed_id'] = $this->claimed_id; |
||
678 | } |
||
679 | |||
680 | return $this->build_url(parse_url($this->server) |
||
681 | , array('query' => http_build_query($params, '', '&'))); |
||
682 | } |
||
683 | |||
684 | /** |
||
685 | * Returns authentication url. Usually, you want to redirect your user to it. |
||
686 | * @return String The authentication url. |
||
687 | * @param String $select_identifier Whether to request OP to select identity for an user in OpenID 2. Does not affect OpenID 1. |
||
0 ignored issues
–
show
There is no parameter named
$select_identifier . Was it maybe removed?
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. Consider the following example. The parameter /**
* @param array $germany
* @param array $island
* @param array $italy
*/
function finale($germany, $island) {
return "2:1";
}
The most likely cause is that the parameter was removed, but the annotation was not. ![]() |
|||
688 | * @throws ErrorException |
||
689 | */ |
||
690 | function authUrl($immediate = false) |
||
0 ignored issues
–
show
|
|||
691 | { |
||
692 | if ($this->setup_url && !$immediate) { |
||
693 | return $this->setup_url; |
||
694 | } |
||
695 | if (!$this->server) { |
||
696 | $this->discover($this->identity); |
||
697 | } |
||
698 | |||
699 | if ($this->version == 2) { |
||
700 | return $this->authUrl_v2($immediate); |
||
701 | } |
||
702 | return $this->authUrl_v1($immediate); |
||
703 | } |
||
704 | |||
705 | /** |
||
706 | * Performs OpenID verification with the OP. |
||
707 | * @return Bool Whether the verification was successful. |
||
708 | * @throws ErrorException |
||
709 | */ |
||
710 | function validate() |
||
0 ignored issues
–
show
|
|||
711 | { |
||
712 | # If the request was using immediate mode, a failure may be reported |
||
0 ignored issues
–
show
|
|||
713 | # by presenting user_setup_url (for 1.1) or reporting |
||
0 ignored issues
–
show
|
|||
714 | # mode 'setup_needed' (for 2.0). Also catching all modes other than |
||
0 ignored issues
–
show
|
|||
715 | # id_res, in order to avoid throwing errors. |
||
0 ignored issues
–
show
|
|||
716 | if (isset($this->data['openid_user_setup_url'])) { |
||
717 | $this->setup_url = $this->data['openid_user_setup_url']; |
||
718 | return false; |
||
719 | } |
||
720 | if ($this->mode != 'id_res') { |
||
0 ignored issues
–
show
The property
mode does not exist on object<LightOpenID> . Since you implemented __get , maybe consider adding a @property annotation.
Since your code implements the magic getter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
If the property has read access only, you can use the @property-read annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
721 | return false; |
||
722 | } |
||
723 | |||
724 | $this->claimed_id = isset($this->data['openid_claimed_id']) ? $this->data['openid_claimed_id'] : $this->data['openid_identity']; |
||
725 | $params = array( |
||
726 | 'openid.assoc_handle' => $this->data['openid_assoc_handle'], |
||
727 | 'openid.signed' => $this->data['openid_signed'], |
||
728 | 'openid.sig' => $this->data['openid_sig'], |
||
729 | ); |
||
730 | |||
731 | if (isset($this->data['openid_ns'])) { |
||
732 | # We're dealing with an OpenID 2.0 server, so let's set an ns |
||
0 ignored issues
–
show
|
|||
733 | # Even though we should know location of the endpoint, |
||
0 ignored issues
–
show
|
|||
734 | # we still need to verify it by discovery, so $server is not set here |
||
0 ignored issues
–
show
|
|||
735 | $params['openid.ns'] = 'http://specs.openid.net/auth/2.0'; |
||
736 | } elseif (isset($this->data['openid_claimed_id']) |
||
737 | && $this->data['openid_claimed_id'] != $this->data['openid_identity'] |
||
738 | ) { |
||
739 | # If it's an OpenID 1 provider, and we've got claimed_id, |
||
0 ignored issues
–
show
|
|||
740 | # we have to append it to the returnUrl, like authUrl_v1 does. |
||
0 ignored issues
–
show
|
|||
741 | $this->returnUrl .= (strpos($this->returnUrl, '?') ? '&' : '?') |
||
742 | . 'openid.claimed_id=' . $this->claimed_id; |
||
743 | } |
||
744 | |||
745 | if ($this->data['openid_return_to'] != $this->returnUrl) { |
||
746 | # The return_to url must match the url of current request. |
||
0 ignored issues
–
show
|
|||
747 | # I'm assuing that noone will set the returnUrl to something that doesn't make sense. |
||
0 ignored issues
–
show
|
|||
748 | return false; |
||
749 | } |
||
750 | |||
751 | $server = $this->discover($this->claimed_id); |
||
752 | |||
753 | foreach (explode(',', $this->data['openid_signed']) as $item) { |
||
754 | # Checking whether magic_quotes_gpc is turned on, because |
||
0 ignored issues
–
show
|
|||
755 | # the function may fail if it is. For example, when fetching |
||
0 ignored issues
–
show
|
|||
756 | # AX namePerson, it might containg an apostrophe, which will be escaped. |
||
0 ignored issues
–
show
|
|||
757 | # In such case, validation would fail, since we'd send different data than OP |
||
0 ignored issues
–
show
|
|||
758 | # wants to verify. stripslashes() should solve that problem, but we can't |
||
0 ignored issues
–
show
|
|||
759 | # use it when magic_quotes is off. |
||
0 ignored issues
–
show
|
|||
760 | $value = $this->data['openid_' . str_replace('.', '_', $item)]; |
||
761 | $params['openid.' . $item] = function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc() ? stripslashes($value) : $value; |
||
762 | |||
763 | } |
||
764 | |||
765 | $params['openid.mode'] = 'check_authentication'; |
||
766 | |||
767 | $response = $this->request($server, 'POST', $params); |
||
768 | |||
769 | return preg_match('/is_valid\s*:\s*true/i', $response); |
||
770 | } |
||
771 | |||
772 | protected function getAxAttributes() |
||
773 | { |
||
774 | $alias = null; |
||
775 | if (isset($this->data['openid_ns_ax']) |
||
776 | && $this->data['openid_ns_ax'] != 'http://openid.net/srv/ax/1.0' |
||
777 | ) { # It's the most likely case, so we'll check it before |
||
0 ignored issues
–
show
|
|||
778 | $alias = 'ax'; |
||
779 | } else { |
||
780 | # 'ax' prefix is either undefined, or points to another extension, |
||
0 ignored issues
–
show
|
|||
781 | # so we search for another prefix |
||
0 ignored issues
–
show
|
|||
782 | foreach ($this->data as $key => $val) { |
||
783 | if (substr($key, 0, strlen('openid_ns_')) == 'openid_ns_' |
||
784 | && $val == 'http://openid.net/srv/ax/1.0' |
||
785 | ) { |
||
786 | $alias = substr($key, strlen('openid_ns_')); |
||
787 | break; |
||
788 | } |
||
789 | } |
||
790 | } |
||
791 | if (!$alias) { |
||
0 ignored issues
–
show
The expression
$alias of type string|null is loosely compared to false ; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
792 | # An alias for AX schema has not been found, |
||
0 ignored issues
–
show
|
|||
793 | # so there is no AX data in the OP's response |
||
0 ignored issues
–
show
|
|||
794 | return array(); |
||
795 | } |
||
796 | |||
797 | $attributes = array(); |
||
798 | foreach (explode(',', $this->data['openid_signed']) as $key) { |
||
799 | $keyMatch = $alias . '.value.'; |
||
800 | if (substr($key, 0, strlen($keyMatch)) != $keyMatch) { |
||
801 | continue; |
||
802 | } |
||
803 | $key = substr($key, strlen($keyMatch)); |
||
804 | if (!isset($this->data['openid_' . $alias . '_type_' . $key])) { |
||
805 | # OP is breaking the spec by returning a field without |
||
0 ignored issues
–
show
|
|||
806 | # associated ns. This shouldn't happen, but it's better |
||
0 ignored issues
–
show
|
|||
807 | # to check, than cause an E_NOTICE. |
||
0 ignored issues
–
show
|
|||
808 | continue; |
||
809 | } |
||
810 | $value = $this->data['openid_' . $alias . '_value_' . $key]; |
||
811 | $key = substr($this->data['openid_' . $alias . '_type_' . $key], |
||
812 | strlen('http://axschema.org/')); |
||
813 | |||
814 | $attributes[$key] = $value; |
||
815 | } |
||
816 | return $attributes; |
||
817 | } |
||
818 | |||
819 | protected function getSregAttributes() |
||
820 | { |
||
821 | $attributes = array(); |
||
822 | $sreg_to_ax = array_flip(self::$ax_to_sreg); |
||
823 | foreach (explode(',', $this->data['openid_signed']) as $key) { |
||
824 | $keyMatch = 'sreg.'; |
||
825 | if (substr($key, 0, strlen($keyMatch)) != $keyMatch) { |
||
826 | continue; |
||
827 | } |
||
828 | $key = substr($key, strlen($keyMatch)); |
||
829 | if (!isset($sreg_to_ax[$key])) { |
||
830 | # The field name isn't part of the SREG spec, so we ignore it. |
||
0 ignored issues
–
show
|
|||
831 | continue; |
||
832 | } |
||
833 | $attributes[$sreg_to_ax[$key]] = $this->data['openid_sreg_' . $key]; |
||
834 | } |
||
835 | return $attributes; |
||
836 | } |
||
837 | |||
838 | /** |
||
839 | * Gets AX/SREG attributes provided by OP. should be used only after successful validaton. |
||
840 | * Note that it does not guarantee that any of the required/optional parameters will be present, |
||
841 | * or that there will be no other attributes besides those specified. |
||
842 | * In other words. OP may provide whatever information it wants to. |
||
843 | * * SREG names will be mapped to AX names. |
||
844 | * * @return Array Array of attributes with keys being the AX schema names, e.g. 'contact/email' |
||
845 | * @see http://www.axschema.org/types/ |
||
846 | */ |
||
847 | function getAttributes() |
||
0 ignored issues
–
show
|
|||
848 | { |
||
849 | if (isset($this->data['openid_ns']) |
||
850 | && $this->data['openid_ns'] == 'http://specs.openid.net/auth/2.0' |
||
851 | ) { # OpenID 2.0 |
||
0 ignored issues
–
show
|
|||
852 | # We search for both AX and SREG attributes, with AX taking precedence. |
||
0 ignored issues
–
show
|
|||
853 | return $this->getAxAttributes() + $this->getSregAttributes(); |
||
854 | } |
||
855 | return $this->getSregAttributes(); |
||
856 | } |
||
857 | } |
||
0 ignored issues
–
show
|
|||
858 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.