|
TYPO3 API
SVNRelease
|
00001 <?php 00002 00003 /** 00004 * This is the PHP OpenID library by JanRain, Inc. 00005 * 00006 * This module contains core utility functionality used by the 00007 * library. See Consumer.php and Server.php for the consumer and 00008 * server implementations. 00009 * 00010 * PHP versions 4 and 5 00011 * 00012 * LICENSE: See the COPYING file included in this distribution. 00013 * 00014 * @package OpenID 00015 * @author JanRain, Inc. <openid@janrain.com> 00016 * @copyright 2005-2008 Janrain, Inc. 00017 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache 00018 */ 00019 00020 /** 00021 * The library version string 00022 */ 00023 define('Auth_OpenID_VERSION', '2.1.2'); 00024 00025 /** 00026 * Require the fetcher code. 00027 */ 00028 require_once "Auth/Yadis/PlainHTTPFetcher.php"; 00029 require_once "Auth/Yadis/ParanoidHTTPFetcher.php"; 00030 require_once "Auth/OpenID/BigMath.php"; 00031 require_once "Auth/OpenID/URINorm.php"; 00032 00033 /** 00034 * Status code returned by the server when the only option is to show 00035 * an error page, since we do not have enough information to redirect 00036 * back to the consumer. The associated value is an error message that 00037 * should be displayed on an HTML error page. 00038 * 00039 * @see Auth_OpenID_Server 00040 */ 00041 define('Auth_OpenID_LOCAL_ERROR', 'local_error'); 00042 00043 /** 00044 * Status code returned when there is an error to return in key-value 00045 * form to the consumer. The caller should return a 400 Bad Request 00046 * response with content-type text/plain and the value as the body. 00047 * 00048 * @see Auth_OpenID_Server 00049 */ 00050 define('Auth_OpenID_REMOTE_ERROR', 'remote_error'); 00051 00052 /** 00053 * Status code returned when there is a key-value form OK response to 00054 * the consumer. The value associated with this code is the 00055 * response. The caller should return a 200 OK response with 00056 * content-type text/plain and the value as the body. 00057 * 00058 * @see Auth_OpenID_Server 00059 */ 00060 define('Auth_OpenID_REMOTE_OK', 'remote_ok'); 00061 00062 /** 00063 * Status code returned when there is a redirect back to the 00064 * consumer. The value is the URL to redirect back to. The caller 00065 * should return a 302 Found redirect with a Location: header 00066 * containing the URL. 00067 * 00068 * @see Auth_OpenID_Server 00069 */ 00070 define('Auth_OpenID_REDIRECT', 'redirect'); 00071 00072 /** 00073 * Status code returned when the caller needs to authenticate the 00074 * user. The associated value is a {@link Auth_OpenID_ServerRequest} 00075 * object that can be used to complete the authentication. If the user 00076 * has taken some authentication action, use the retry() method of the 00077 * {@link Auth_OpenID_ServerRequest} object to complete the request. 00078 * 00079 * @see Auth_OpenID_Server 00080 */ 00081 define('Auth_OpenID_DO_AUTH', 'do_auth'); 00082 00083 /** 00084 * Status code returned when there were no OpenID arguments 00085 * passed. This code indicates that the caller should return a 200 OK 00086 * response and display an HTML page that says that this is an OpenID 00087 * server endpoint. 00088 * 00089 * @see Auth_OpenID_Server 00090 */ 00091 define('Auth_OpenID_DO_ABOUT', 'do_about'); 00092 00093 /** 00094 * Defines for regexes and format checking. 00095 */ 00096 define('Auth_OpenID_letters', 00097 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); 00098 00099 define('Auth_OpenID_digits', 00100 "0123456789"); 00101 00102 define('Auth_OpenID_punct', 00103 "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"); 00104 00105 if (Auth_OpenID_getMathLib() === null) { 00106 Auth_OpenID_setNoMathSupport(); 00107 } 00108 00109 /** 00110 * The OpenID utility function class. 00111 * 00112 * @package OpenID 00113 * @access private 00114 */ 00115 class Auth_OpenID { 00116 00117 /** 00118 * Return true if $thing is an Auth_OpenID_FailureResponse object; 00119 * false if not. 00120 * 00121 * @access private 00122 */ 00123 function isFailure($thing) 00124 { 00125 return is_a($thing, 'Auth_OpenID_FailureResponse'); 00126 } 00127 00128 /** 00129 * Gets the query data from the server environment based on the 00130 * request method used. If GET was used, this looks at 00131 * $_SERVER['QUERY_STRING'] directly. If POST was used, this 00132 * fetches data from the special php://input file stream. 00133 * 00134 * Returns an associative array of the query arguments. 00135 * 00136 * Skips invalid key/value pairs (i.e. keys with no '=value' 00137 * portion). 00138 * 00139 * Returns an empty array if neither GET nor POST was used, or if 00140 * POST was used but php://input cannot be opened. 00141 * 00142 * @access private 00143 */ 00144 function getQuery($query_str=null) 00145 { 00146 $data = array(); 00147 00148 if ($query_str !== null) { 00149 $data = Auth_OpenID::params_from_string($query_str); 00150 } else if (!array_key_exists('REQUEST_METHOD', $_SERVER)) { 00151 // Do nothing. 00152 } else { 00153 // XXX HACK FIXME HORRIBLE. 00154 // 00155 // POSTing to a URL with query parameters is acceptable, but 00156 // we don't have a clean way to distinguish those parameters 00157 // when we need to do things like return_to verification 00158 // which only want to look at one kind of parameter. We're 00159 // going to emulate the behavior of some other environments 00160 // by defaulting to GET and overwriting with POST if POST 00161 // data is available. 00162 $data = Auth_OpenID::params_from_string($_SERVER['QUERY_STRING']); 00163 00164 if ($_SERVER['REQUEST_METHOD'] == 'POST') { 00165 $str = file_get_contents('php://input'); 00166 00167 if ($str === false) { 00168 $post = array(); 00169 } else { 00170 $post = Auth_OpenID::params_from_string($str); 00171 } 00172 00173 $data = array_merge($data, $post); 00174 } 00175 } 00176 00177 return $data; 00178 } 00179 00180 function params_from_string($str) 00181 { 00182 $chunks = explode("&", $str); 00183 00184 $data = array(); 00185 foreach ($chunks as $chunk) { 00186 $parts = explode("=", $chunk, 2); 00187 00188 if (count($parts) != 2) { 00189 continue; 00190 } 00191 00192 list($k, $v) = $parts; 00193 $data[$k] = urldecode($v); 00194 } 00195 00196 return $data; 00197 } 00198 00199 /** 00200 * Create dir_name as a directory if it does not exist. If it 00201 * exists, make sure that it is, in fact, a directory. Returns 00202 * true if the operation succeeded; false if not. 00203 * 00204 * @access private 00205 */ 00206 function ensureDir($dir_name) 00207 { 00208 if (is_dir($dir_name) || @mkdir($dir_name)) { 00209 return true; 00210 } else { 00211 $parent_dir = dirname($dir_name); 00212 00213 // Terminal case; there is no parent directory to create. 00214 if ($parent_dir == $dir_name) { 00215 return true; 00216 } 00217 00218 return (Auth_OpenID::ensureDir($parent_dir) && @mkdir($dir_name)); 00219 } 00220 } 00221 00222 /** 00223 * Adds a string prefix to all values of an array. Returns a new 00224 * array containing the prefixed values. 00225 * 00226 * @access private 00227 */ 00228 function addPrefix($values, $prefix) 00229 { 00230 $new_values = array(); 00231 foreach ($values as $s) { 00232 $new_values[] = $prefix . $s; 00233 } 00234 return $new_values; 00235 } 00236 00237 /** 00238 * Convenience function for getting array values. Given an array 00239 * $arr and a key $key, get the corresponding value from the array 00240 * or return $default if the key is absent. 00241 * 00242 * @access private 00243 */ 00244 function arrayGet($arr, $key, $fallback = null) 00245 { 00246 if (is_array($arr)) { 00247 if (array_key_exists($key, $arr)) { 00248 return $arr[$key]; 00249 } else { 00250 return $fallback; 00251 } 00252 } else { 00253 trigger_error("Auth_OpenID::arrayGet (key = ".$key.") expected " . 00254 "array as first parameter, got " . 00255 gettype($arr), E_USER_WARNING); 00256 00257 return false; 00258 } 00259 } 00260 00261 /** 00262 * Replacement for PHP's broken parse_str. 00263 */ 00264 function parse_str($query) 00265 { 00266 if ($query === null) { 00267 return null; 00268 } 00269 00270 $parts = explode('&', $query); 00271 00272 $new_parts = array(); 00273 for ($i = 0; $i < count($parts); $i++) { 00274 $pair = explode('=', $parts[$i]); 00275 00276 if (count($pair) != 2) { 00277 continue; 00278 } 00279 00280 list($key, $value) = $pair; 00281 $new_parts[$key] = urldecode($value); 00282 } 00283 00284 return $new_parts; 00285 } 00286 00287 /** 00288 * Implements the PHP 5 'http_build_query' functionality. 00289 * 00290 * @access private 00291 * @param array $data Either an array key/value pairs or an array 00292 * of arrays, each of which holding two values: a key and a value, 00293 * sequentially. 00294 * @return string $result The result of url-encoding the key/value 00295 * pairs from $data into a URL query string 00296 * (e.g. "username=bob&id=56"). 00297 */ 00298 function httpBuildQuery($data) 00299 { 00300 $pairs = array(); 00301 foreach ($data as $key => $value) { 00302 if (is_array($value)) { 00303 $pairs[] = urlencode($value[0])."=".urlencode($value[1]); 00304 } else { 00305 $pairs[] = urlencode($key)."=".urlencode($value); 00306 } 00307 } 00308 return implode("&", $pairs); 00309 } 00310 00311 /** 00312 * "Appends" query arguments onto a URL. The URL may or may not 00313 * already have arguments (following a question mark). 00314 * 00315 * @access private 00316 * @param string $url A URL, which may or may not already have 00317 * arguments. 00318 * @param array $args Either an array key/value pairs or an array of 00319 * arrays, each of which holding two values: a key and a value, 00320 * sequentially. If $args is an ordinary key/value array, the 00321 * parameters will be added to the URL in sorted alphabetical order; 00322 * if $args is an array of arrays, their order will be preserved. 00323 * @return string $url The original URL with the new parameters added. 00324 * 00325 */ 00326 function appendArgs($url, $args) 00327 { 00328 if (count($args) == 0) { 00329 return $url; 00330 } 00331 00332 // Non-empty array; if it is an array of arrays, use 00333 // multisort; otherwise use sort. 00334 if (array_key_exists(0, $args) && 00335 is_array($args[0])) { 00336 // Do nothing here. 00337 } else { 00338 $keys = array_keys($args); 00339 sort($keys); 00340 $new_args = array(); 00341 foreach ($keys as $key) { 00342 $new_args[] = array($key, $args[$key]); 00343 } 00344 $args = $new_args; 00345 } 00346 00347 $sep = '?'; 00348 if (strpos($url, '?') !== false) { 00349 $sep = '&'; 00350 } 00351 00352 return $url . $sep . Auth_OpenID::httpBuildQuery($args); 00353 } 00354 00355 /** 00356 * Implements python's urlunparse, which is not available in PHP. 00357 * Given the specified components of a URL, this function rebuilds 00358 * and returns the URL. 00359 * 00360 * @access private 00361 * @param string $scheme The scheme (e.g. 'http'). Defaults to 'http'. 00362 * @param string $host The host. Required. 00363 * @param string $port The port. 00364 * @param string $path The path. 00365 * @param string $query The query. 00366 * @param string $fragment The fragment. 00367 * @return string $url The URL resulting from assembling the 00368 * specified components. 00369 */ 00370 function urlunparse($scheme, $host, $port = null, $path = '/', 00371 $query = '', $fragment = '') 00372 { 00373 00374 if (!$scheme) { 00375 $scheme = 'http'; 00376 } 00377 00378 if (!$host) { 00379 return false; 00380 } 00381 00382 if (!$path) { 00383 $path = ''; 00384 } 00385 00386 $result = $scheme . "://" . $host; 00387 00388 if ($port) { 00389 $result .= ":" . $port; 00390 } 00391 00392 $result .= $path; 00393 00394 if ($query) { 00395 $result .= "?" . $query; 00396 } 00397 00398 if ($fragment) { 00399 $result .= "#" . $fragment; 00400 } 00401 00402 return $result; 00403 } 00404 00405 /** 00406 * Given a URL, this "normalizes" it by adding a trailing slash 00407 * and / or a leading http:// scheme where necessary. Returns 00408 * null if the original URL is malformed and cannot be normalized. 00409 * 00410 * @access private 00411 * @param string $url The URL to be normalized. 00412 * @return mixed $new_url The URL after normalization, or null if 00413 * $url was malformed. 00414 */ 00415 function normalizeUrl($url) 00416 { 00417 @$parsed = parse_url($url); 00418 00419 if (!$parsed) { 00420 return null; 00421 } 00422 00423 if (isset($parsed['scheme']) && 00424 isset($parsed['host'])) { 00425 $scheme = strtolower($parsed['scheme']); 00426 if (!in_array($scheme, array('http', 'https'))) { 00427 return null; 00428 } 00429 } else { 00430 $url = 'http://' . $url; 00431 } 00432 00433 $normalized = Auth_OpenID_urinorm($url); 00434 if ($normalized === null) { 00435 return null; 00436 } 00437 list($defragged, $frag) = Auth_OpenID::urldefrag($normalized); 00438 return $defragged; 00439 } 00440 00441 /** 00442 * Replacement (wrapper) for PHP's intval() because it's broken. 00443 * 00444 * @access private 00445 */ 00446 function intval($value) 00447 { 00448 $re = "/^\\d+$/"; 00449 00450 if (!preg_match($re, $value)) { 00451 return false; 00452 } 00453 00454 return intval($value); 00455 } 00456 00457 /** 00458 * Count the number of bytes in a string independently of 00459 * multibyte support conditions. 00460 * 00461 * @param string $str The string of bytes to count. 00462 * @return int The number of bytes in $str. 00463 */ 00464 function bytes($str) 00465 { 00466 return strlen(bin2hex($str)) / 2; 00467 } 00468 00469 /** 00470 * Get the bytes in a string independently of multibyte support 00471 * conditions. 00472 */ 00473 function toBytes($str) 00474 { 00475 $hex = bin2hex($str); 00476 00477 if (!$hex) { 00478 return array(); 00479 } 00480 00481 $b = array(); 00482 for ($i = 0; $i < strlen($hex); $i += 2) { 00483 $b[] = chr(base_convert(substr($hex, $i, 2), 16, 10)); 00484 } 00485 00486 return $b; 00487 } 00488 00489 function urldefrag($url) 00490 { 00491 $parts = explode("#", $url, 2); 00492 00493 if (count($parts) == 1) { 00494 return array($parts[0], ""); 00495 } else { 00496 return $parts; 00497 } 00498 } 00499 00500 function filter($callback, &$sequence) 00501 { 00502 $result = array(); 00503 00504 foreach ($sequence as $item) { 00505 if (call_user_func_array($callback, array($item))) { 00506 $result[] = $item; 00507 } 00508 } 00509 00510 return $result; 00511 } 00512 00513 function update(&$dest, &$src) 00514 { 00515 foreach ($src as $k => $v) { 00516 $dest[$k] = $v; 00517 } 00518 } 00519 00520 /** 00521 * Wrap PHP's standard error_log functionality. Use this to 00522 * perform all logging. It will interpolate any additional 00523 * arguments into the format string before logging. 00524 * 00525 * @param string $format_string The sprintf format for the message 00526 */ 00527 function log($format_string) 00528 { 00529 $args = func_get_args(); 00530 $message = call_user_func_array('sprintf', $args); 00531 error_log($message); 00532 } 00533 00534 function autoSubmitHTML($form, $title="OpenId transaction in progress") 00535 { 00536 return("<html>". 00537 "<head><title>". 00538 $title . 00539 "</title></head>". 00540 "<body onload='document.forms[0].submit();'>". 00541 $form . 00542 "<script>". 00543 "var elements = document.forms[0].elements;". 00544 "for (var i = 0; i < elements.length; i++) {". 00545 " elements[i].style.display = \"none\";". 00546 "}". 00547 "</script>". 00548 "</body>". 00549 "</html>"); 00550 } 00551 } 00552 ?>
1.8.0