PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/concrete/libraries/3rdparty/Auth/OpenID.php

https://bitbucket.org/selfeky/xclusivescardwebsite
PHP | 552 lines | 467 code | 12 blank | 73 comment | 0 complexity | 3be9f681eacbf1b296c136dc8a3ea7db MD5 | raw file
  1. <?php
  2. /**
  3. * This is the PHP OpenID library by JanRain, Inc.
  4. *
  5. * This module contains core utility functionality used by the
  6. * library. See Consumer.php and Server.php for the consumer and
  7. * server implementations.
  8. *
  9. * PHP versions 4 and 5
  10. *
  11. * LICENSE: See the COPYING file included in this distribution.
  12. *
  13. * @package OpenID
  14. * @author JanRain, Inc. <openid@janrain.com>
  15. * @copyright 2005-2008 Janrain, Inc.
  16. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
  17. */
  18. /**
  19. * The library version string
  20. */
  21. define('Auth_OpenID_VERSION', '2.1.2');
  22. /**
  23. * Require the fetcher code.
  24. */
  25. require_once "Auth/Yadis/PlainHTTPFetcher.php";
  26. require_once "Auth/Yadis/ParanoidHTTPFetcher.php";
  27. require_once "Auth/OpenID/BigMath.php";
  28. require_once "Auth/OpenID/URINorm.php";
  29. /**
  30. * Status code returned by the server when the only option is to show
  31. * an error page, since we do not have enough information to redirect
  32. * back to the consumer. The associated value is an error message that
  33. * should be displayed on an HTML error page.
  34. *
  35. * @see Auth_OpenID_Server
  36. */
  37. define('Auth_OpenID_LOCAL_ERROR', 'local_error');
  38. /**
  39. * Status code returned when there is an error to return in key-value
  40. * form to the consumer. The caller should return a 400 Bad Request
  41. * response with content-type text/plain and the value as the body.
  42. *
  43. * @see Auth_OpenID_Server
  44. */
  45. define('Auth_OpenID_REMOTE_ERROR', 'remote_error');
  46. /**
  47. * Status code returned when there is a key-value form OK response to
  48. * the consumer. The value associated with this code is the
  49. * response. The caller should return a 200 OK response with
  50. * content-type text/plain and the value as the body.
  51. *
  52. * @see Auth_OpenID_Server
  53. */
  54. define('Auth_OpenID_REMOTE_OK', 'remote_ok');
  55. /**
  56. * Status code returned when there is a redirect back to the
  57. * consumer. The value is the URL to redirect back to. The caller
  58. * should return a 302 Found redirect with a Location: header
  59. * containing the URL.
  60. *
  61. * @see Auth_OpenID_Server
  62. */
  63. define('Auth_OpenID_REDIRECT', 'redirect');
  64. /**
  65. * Status code returned when the caller needs to authenticate the
  66. * user. The associated value is a {@link Auth_OpenID_ServerRequest}
  67. * object that can be used to complete the authentication. If the user
  68. * has taken some authentication action, use the retry() method of the
  69. * {@link Auth_OpenID_ServerRequest} object to complete the request.
  70. *
  71. * @see Auth_OpenID_Server
  72. */
  73. define('Auth_OpenID_DO_AUTH', 'do_auth');
  74. /**
  75. * Status code returned when there were no OpenID arguments
  76. * passed. This code indicates that the caller should return a 200 OK
  77. * response and display an HTML page that says that this is an OpenID
  78. * server endpoint.
  79. *
  80. * @see Auth_OpenID_Server
  81. */
  82. define('Auth_OpenID_DO_ABOUT', 'do_about');
  83. /**
  84. * Defines for regexes and format checking.
  85. */
  86. define('Auth_OpenID_letters',
  87. "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
  88. define('Auth_OpenID_digits',
  89. "0123456789");
  90. define('Auth_OpenID_punct',
  91. "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~");
  92. if (Auth_OpenID_getMathLib() === null) {
  93. Auth_OpenID_setNoMathSupport();
  94. }
  95. /**
  96. * The OpenID utility function class.
  97. *
  98. * @package OpenID
  99. * @access private
  100. */
  101. class Auth_OpenID {
  102. /**
  103. * Return true if $thing is an Auth_OpenID_FailureResponse object;
  104. * false if not.
  105. *
  106. * @access private
  107. */
  108. function isFailure($thing)
  109. {
  110. return is_a($thing, 'Auth_OpenID_FailureResponse');
  111. }
  112. /**
  113. * Gets the query data from the server environment based on the
  114. * request method used. If GET was used, this looks at
  115. * $_SERVER['QUERY_STRING'] directly. If POST was used, this
  116. * fetches data from the special php://input file stream.
  117. *
  118. * Returns an associative array of the query arguments.
  119. *
  120. * Skips invalid key/value pairs (i.e. keys with no '=value'
  121. * portion).
  122. *
  123. * Returns an empty array if neither GET nor POST was used, or if
  124. * POST was used but php://input cannot be opened.
  125. *
  126. * @access private
  127. */
  128. function getQuery($query_str=null)
  129. {
  130. $data = array();
  131. if ($query_str !== null) {
  132. $data = Auth_OpenID::params_from_string($query_str);
  133. } else if (!array_key_exists('REQUEST_METHOD', $_SERVER)) {
  134. // Do nothing.
  135. } else {
  136. // XXX HACK FIXME HORRIBLE.
  137. //
  138. // POSTing to a URL with query parameters is acceptable, but
  139. // we don't have a clean way to distinguish those parameters
  140. // when we need to do things like return_to verification
  141. // which only want to look at one kind of parameter. We're
  142. // going to emulate the behavior of some other environments
  143. // by defaulting to GET and overwriting with POST if POST
  144. // data is available.
  145. $data = Auth_OpenID::params_from_string($_SERVER['QUERY_STRING']);
  146. if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  147. $str = file_get_contents('php://input');
  148. if ($str === false) {
  149. $post = array();
  150. } else {
  151. $post = Auth_OpenID::params_from_string($str);
  152. }
  153. $data = array_merge($data, $post);
  154. }
  155. }
  156. return $data;
  157. }
  158. function params_from_string($str)
  159. {
  160. $chunks = explode("&", $str);
  161. $data = array();
  162. foreach ($chunks as $chunk) {
  163. $parts = explode("=", $chunk, 2);
  164. if (count($parts) != 2) {
  165. continue;
  166. }
  167. list($k, $v) = $parts;
  168. $data[$k] = urldecode($v);
  169. }
  170. return $data;
  171. }
  172. /**
  173. * Create dir_name as a directory if it does not exist. If it
  174. * exists, make sure that it is, in fact, a directory. Returns
  175. * true if the operation succeeded; false if not.
  176. *
  177. * @access private
  178. */
  179. function ensureDir($dir_name)
  180. {
  181. if (is_dir($dir_name) || @mkdir($dir_name)) {
  182. return true;
  183. } else {
  184. $parent_dir = dirname($dir_name);
  185. // Terminal case; there is no parent directory to create.
  186. if ($parent_dir == $dir_name) {
  187. return true;
  188. }
  189. return (Auth_OpenID::ensureDir($parent_dir) && @mkdir($dir_name));
  190. }
  191. }
  192. /**
  193. * Adds a string prefix to all values of an array. Returns a new
  194. * array containing the prefixed values.
  195. *
  196. * @access private
  197. */
  198. function addPrefix($values, $prefix)
  199. {
  200. $new_values = array();
  201. foreach ($values as $s) {
  202. $new_values[] = $prefix . $s;
  203. }
  204. return $new_values;
  205. }
  206. /**
  207. * Convenience function for getting array values. Given an array
  208. * $arr and a key $key, get the corresponding value from the array
  209. * or return $default if the key is absent.
  210. *
  211. * @access private
  212. */
  213. function arrayGet($arr, $key, $fallback = null)
  214. {
  215. if (is_array($arr)) {
  216. if (array_key_exists($key, $arr)) {
  217. return $arr[$key];
  218. } else {
  219. return $fallback;
  220. }
  221. } else {
  222. trigger_error("Auth_OpenID::arrayGet (key = ".$key.") expected " .
  223. "array as first parameter, got " .
  224. gettype($arr), E_USER_WARNING);
  225. return false;
  226. }
  227. }
  228. /**
  229. * Replacement for PHP's broken parse_str.
  230. */
  231. function parse_str($query)
  232. {
  233. if ($query === null) {
  234. return null;
  235. }
  236. $parts = explode('&', $query);
  237. $new_parts = array();
  238. for ($i = 0; $i < count($parts); $i++) {
  239. $pair = explode('=', $parts[$i]);
  240. if (count($pair) != 2) {
  241. continue;
  242. }
  243. list($key, $value) = $pair;
  244. $new_parts[$key] = urldecode($value);
  245. }
  246. return $new_parts;
  247. }
  248. /**
  249. * Implements the PHP 5 'http_build_query' functionality.
  250. *
  251. * @access private
  252. * @param array $data Either an array key/value pairs or an array
  253. * of arrays, each of which holding two values: a key and a value,
  254. * sequentially.
  255. * @return string $result The result of url-encoding the key/value
  256. * pairs from $data into a URL query string
  257. * (e.g. "username=bob&id=56").
  258. */
  259. function httpBuildQuery($data)
  260. {
  261. $pairs = array();
  262. foreach ($data as $key => $value) {
  263. if (is_array($value)) {
  264. $pairs[] = urlencode($value[0])."=".urlencode($value[1]);
  265. } else {
  266. $pairs[] = urlencode($key)."=".urlencode($value);
  267. }
  268. }
  269. return implode("&", $pairs);
  270. }
  271. /**
  272. * "Appends" query arguments onto a URL. The URL may or may not
  273. * already have arguments (following a question mark).
  274. *
  275. * @access private
  276. * @param string $url A URL, which may or may not already have
  277. * arguments.
  278. * @param array $args Either an array key/value pairs or an array of
  279. * arrays, each of which holding two values: a key and a value,
  280. * sequentially. If $args is an ordinary key/value array, the
  281. * parameters will be added to the URL in sorted alphabetical order;
  282. * if $args is an array of arrays, their order will be preserved.
  283. * @return string $url The original URL with the new parameters added.
  284. *
  285. */
  286. function appendArgs($url, $args)
  287. {
  288. if (count($args) == 0) {
  289. return $url;
  290. }
  291. // Non-empty array; if it is an array of arrays, use
  292. // multisort; otherwise use sort.
  293. if (array_key_exists(0, $args) &&
  294. is_array($args[0])) {
  295. // Do nothing here.
  296. } else {
  297. $keys = array_keys($args);
  298. sort($keys);
  299. $new_args = array();
  300. foreach ($keys as $key) {
  301. $new_args[] = array($key, $args[$key]);
  302. }
  303. $args = $new_args;
  304. }
  305. $sep = '?';
  306. if (strpos($url, '?') !== false) {
  307. $sep = '&';
  308. }
  309. return $url . $sep . Auth_OpenID::httpBuildQuery($args);
  310. }
  311. /**
  312. * Implements python's urlunparse, which is not available in PHP.
  313. * Given the specified components of a URL, this function rebuilds
  314. * and returns the URL.
  315. *
  316. * @access private
  317. * @param string $scheme The scheme (e.g. 'http'). Defaults to 'http'.
  318. * @param string $host The host. Required.
  319. * @param string $port The port.
  320. * @param string $path The path.
  321. * @param string $query The query.
  322. * @param string $fragment The fragment.
  323. * @return string $url The URL resulting from assembling the
  324. * specified components.
  325. */
  326. function urlunparse($scheme, $host, $port = null, $path = '/',
  327. $query = '', $fragment = '')
  328. {
  329. if (!$scheme) {
  330. $scheme = 'http';
  331. }
  332. if (!$host) {
  333. return false;
  334. }
  335. if (!$path) {
  336. $path = '';
  337. }
  338. $result = $scheme . "://" . $host;
  339. if ($port) {
  340. $result .= ":" . $port;
  341. }
  342. $result .= $path;
  343. if ($query) {
  344. $result .= "?" . $query;
  345. }
  346. if ($fragment) {
  347. $result .= "#" . $fragment;
  348. }
  349. return $result;
  350. }
  351. /**
  352. * Given a URL, this "normalizes" it by adding a trailing slash
  353. * and / or a leading http:// scheme where necessary. Returns
  354. * null if the original URL is malformed and cannot be normalized.
  355. *
  356. * @access private
  357. * @param string $url The URL to be normalized.
  358. * @return mixed $new_url The URL after normalization, or null if
  359. * $url was malformed.
  360. */
  361. function normalizeUrl($url)
  362. {
  363. @$parsed = parse_url($url);
  364. if (!$parsed) {
  365. return null;
  366. }
  367. if (isset($parsed['scheme']) &&
  368. isset($parsed['host'])) {
  369. $scheme = strtolower($parsed['scheme']);
  370. if (!in_array($scheme, array('http', 'https'))) {
  371. return null;
  372. }
  373. } else {
  374. $url = 'http://' . $url;
  375. }
  376. $normalized = Auth_OpenID_urinorm($url);
  377. if ($normalized === null) {
  378. return null;
  379. }
  380. list($defragged, $frag) = Auth_OpenID::urldefrag($normalized);
  381. return $defragged;
  382. }
  383. /**
  384. * Replacement (wrapper) for PHP's intval() because it's broken.
  385. *
  386. * @access private
  387. */
  388. function intval($value)
  389. {
  390. $re = "/^\\d+$/";
  391. if (!preg_match($re, $value)) {
  392. return false;
  393. }
  394. return intval($value);
  395. }
  396. /**
  397. * Count the number of bytes in a string independently of
  398. * multibyte support conditions.
  399. *
  400. * @param string $str The string of bytes to count.
  401. * @return int The number of bytes in $str.
  402. */
  403. function bytes($str)
  404. {
  405. return strlen(bin2hex($str)) / 2;
  406. }
  407. /**
  408. * Get the bytes in a string independently of multibyte support
  409. * conditions.
  410. */
  411. function toBytes($str)
  412. {
  413. $hex = bin2hex($str);
  414. if (!$hex) {
  415. return array();
  416. }
  417. $b = array();
  418. for ($i = 0; $i < strlen($hex); $i += 2) {
  419. $b[] = chr(base_convert(substr($hex, $i, 2), 16, 10));
  420. }
  421. return $b;
  422. }
  423. function urldefrag($url)
  424. {
  425. $parts = explode("#", $url, 2);
  426. if (count($parts) == 1) {
  427. return array($parts[0], "");
  428. } else {
  429. return $parts;
  430. }
  431. }
  432. function filter($callback, &$sequence)
  433. {
  434. $result = array();
  435. foreach ($sequence as $item) {
  436. if (call_user_func_array($callback, array($item))) {
  437. $result[] = $item;
  438. }
  439. }
  440. return $result;
  441. }
  442. function update(&$dest, &$src)
  443. {
  444. foreach ($src as $k => $v) {
  445. $dest[$k] = $v;
  446. }
  447. }
  448. /**
  449. * Wrap PHP's standard error_log functionality. Use this to
  450. * perform all logging. It will interpolate any additional
  451. * arguments into the format string before logging.
  452. *
  453. * @param string $format_string The sprintf format for the message
  454. */
  455. function log($format_string)
  456. {
  457. $args = func_get_args();
  458. $message = call_user_func_array('sprintf', $args);
  459. error_log($message);
  460. }
  461. function autoSubmitHTML($form, $title="OpenId transaction in progress")
  462. {
  463. return("<html>".
  464. "<head><title>".
  465. $title .
  466. "</title></head>".
  467. "<body onload='document.forms[0].submit();'>".
  468. $form .
  469. "<script>".
  470. "var elements = document.forms[0].elements;".
  471. "for (var i = 0; i < elements.length; i++) {".
  472. " elements[i].style.display = \"none\";".
  473. "}".
  474. "</script>".
  475. "</body>".
  476. "</html>");
  477. }
  478. }
  479. ?>