pear/0000755000175000017500000000000011663412405011261 5ustar danieldanielpear/simpleid/0000755000175000017500000000000011710103552013060 5ustar danieldanielpear/simpleid/www/0000755000175000017500000000000011710103552013704 5ustar danieldanielpear/simpleid/www/html/0000755000175000017500000000000011710103552014650 5ustar danieldanielpear/simpleid/www/lib/0000755000175000017500000000000011710103552014452 5ustar danieldanielpear/simpleid/www/extensions/0000755000175000017500000000000011663412406016113 5ustar danieldanielpear/simpleid/www/extensions/ui/0000755000175000017500000000000011710103552016520 5ustar danieldanielpear/simpleid/www/extensions/ax/0000755000175000017500000000000011710103552016513 5ustar danieldanielpear/simpleid/www/extensions/sreg/0000755000175000017500000000000011710103552017043 5ustar danieldanielpear/simpleid/www/extensions/pape/0000755000175000017500000000000011710103552017030 5ustar danieldanielpear/simpleid/cache/0000755000175000017500000000000011663412406014133 5ustar danieldanielpear/simpleid/extensions/0000755000175000017500000000000011710103552015257 5ustar danieldanielpear/simpleid/store/0000755000175000017500000000000011663412406014224 5ustar danieldanielpear/simpleid/identities/0000755000175000017500000000000011710103552015221 5ustar danieldanielsimpleid/0000755000175000017500000000000011746513176012151 5ustar danieldanielsimpleid/www/0000755000175000017500000000000011746513207012770 5ustar danieldanielsimpleid/www/.htaccess.dist0000644000175000017500000000277611710103700015524 0ustar danieldaniel# :mode=htaccess: # # SimpleID # # Copyright (C) Kelvin Mo 2009 # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this program; if not, write to the Free # Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # $Id: .htaccess.dist 286 2010-02-12 08:58:16Z kmo $ # Protect files and directories from prying eyes. Order deny,allow Deny from all # Don't show directory listings for URLs which map to a directory. Options -Indexes # Various rewrite rules. RewriteEngine on # Modify the RewriteBase if you are using SimpleID in a subdirectory and # the rewrite rules are not working properly. #RewriteBase /simpleid # Rewrite URLs RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?q=$1 [L,QSA] # Switch register_globals to off php_value register_globals 0 simpleid/www/config.inc.dist0000644000175000017500000001365211710103700015661 0ustar danieldaniel * define('SIMPLEID_BASE_URL', 'http://www.example.com'); * define('SIMPLEID_BASE_URL', 'http://www.example.com:8888'); * define('SIMPLEID_BASE_URL', 'http://www.example.com/simpleid'); * define('SIMPLEID_BASE_URL', 'https://www.example.com:8888/simpleid'); * * */ define('SIMPLEID_BASE_URL', 'http://www.example.com'); /** * Allow clean URLs. * * URLs used in SimpleID are normally in the form * http://www.example.com/index.php?q=foo. Enabling clean URLs will allow for * SimpleID URLs to be in the form http://www.example.com/foo * * In order to support clean URLs, you must be using Apache with mod_rewrite * enabled. You will need to rename .htaccess.dist in the SimpleID web directory * to .htaccess * * @since 0.8 * */ define('SIMPLEID_CLEAN_URL', false); /** * Directory to store identity information. * * This directory must exist and be readable by the web server. * * For maximum security, it is highly recommended to place this * directory outside your web browser's document root directory, so * that it is not visible to user agents. * */ define('SIMPLEID_IDENTITIES_DIR', '../identities'); /** * Directory to store cache data. * * This directory must exist and be readable and writable by the * web server. * * For maximum security, it is highly recommended to place this * directory outside your web browser's document root directory, so * that it is not visible to user agents. * */ define('SIMPLEID_CACHE_DIR', '../cache'); /** * Persistent data storage mechanism. * * SimpleID provides flexible methods to store and retrieve persistent data. * By default, SimpleID uses the file system to store this data, implemented * in filesystem.store.inc. Users can implement other methods by creating * a file with extension .store.inc and specifying the file through this * setting. * * Generally you do not need to change this setting. * */ define('SIMPLEID_STORE', 'filesystem'); /** * Directory to store persistent data. * * This directory must exist and be readable and writable by the * web server. * * For maximum security, it is highly recommended to place this * directory outside your web browser's document root directory, so * that it is not visible to user agents. * */ define('SIMPLEID_STORE_DIR', '../store'); /** * Allows legacy log-in system. * * Prior to SimpleID 0.6, the login system utilised by SimpleID requires users' * passwords to be sent in plaintext to the web server for verification. This is * an inherent security risk. * * From version 0.6, SimpleID implemented a form of digest authentication, which * means that passwords are not sent in plaintext. For backwards compatibility, * and to support browsers that do not have JavaScript installed, the legacy * method is still supported if the following configuration parameter is set * to true. Otherwise, users must use a browser which supports JavaScript to * log into SimpleID. * * The default is set to false for security reasons. You should not change * this value unless it is absolutely necessary. * * @since 0.6 */ define('SIMPLEID_ALLOW_LEGACY_LOGIN', false); /** * Allows web browsers to save passwords. * * SimpleID prevents web browsers from saving user passwords entered in a user * logs into SimpleID. Setting this value to true will allow browsers to * ask the user whether the password should be saved in the browser's password * store. * * The default is set to false for security reasons. You should not change * this value unless you are certain regarding the security of your browser's * password store. * * @since 0.8 */ define('SIMPLEID_ALLOW_AUTOCOMPLETE', false); /** * Performs additional verification of relying party return URLs. * * When authenticating using OpenID version 2, SimpleID version 0.7 or later * can perform additional verification of the relying party's return URLs under * section 9.2.1 of the OpenID specification. * * The default is set to true for security reasons. However, if your web server * is blocked by your web hosting provider's firewall from accessing outside * servers, then set this to false. * * @since 0.7 * */ define('SIMPLEID_VERIFY_RETURN_URL_USING_REALM', true); /** * Date and time format. * * The date and time format specified using the strftime() syntax. * * See http://www.php.net/strftime for details. * */ define('SIMPLEID_DATE_TIME_FORMAT', '%Y-%m-%d %H:%M:%S %Z'); /** * The number of seconds before associations expire. This is an advanced * option, for which the default setting should work fine. * * Note that for ICAM compliance, this number must be less than 86400. */ define('SIMPLEID_ASSOC_EXPIRES_IN', 3600); /** * SimpleID extensions. * * The SimpleID extensions you wish to load. You should separate the * extensions you wish to load with a comma. * */ define('SIMPLEID_EXTENSIONS', 'sreg,ui'); /** * Log file. * * You can specify a file into which SimpleID will log various diagnostic * messages. * * The log file's directory must exist and must be writable by the web server. * * To disable logging, set this as an empty string. * * @since 0.7 * */ define('SIMPLEID_LOGFILE', ''); /** * The level of detail for log messages. * * You can determine which messages are captured in the log file by specifying * a number between 0 and 5. The higher the number, the more messages are * logged. * * WARNING: Setting the log level to 5 will result in security sensitive * information also being logged. * * This has effect only if logging is enabled. * * @since 0.7 * */ define('SIMPLEID_LOGLEVEL', 4); ?> simpleid/www/version.inc0000644000175000017500000000172411710103700015134 0ustar danieldaniel simpleid/www/user.inc0000644000175000017500000004756111710103700014436 0ustar danieldaniel * James Walker * * Copyright (C) Rowan Kerr and James Walker * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: user.inc 481 2011-12-14 11:41:13Z kmo $ */ /** * User functions. * * @package simpleid * @filesource */ /** * The time the nonce used in the login process will last. */ define('SIMPLEID_LOGIN_NONCE_EXPIRES_IN', 3600); /** * The time (in seconds) the auto login cookie will last. This is currently * set as 2 weeks. */ define('SIMPLEID_USER_AUTOLOGIN_EXPIRES_IN', 1209600); /** * This variable holds data on the currently logged-in user. If the user is * not logged in, this variable is NULL. * * @global array $user */ $user = NULL; /** * Initialises the user system. Loads data for the currently logged-in user, * if any. * * @param string $q the SimpleID command, if any */ function user_init($q = NULL) { global $user; global $xtpl; log_debug('user_init'); $user = NULL; session_set_cookie_params(0); session_name('SESS' . md5(SIMPLEID_BASE_URL)); session_start(); if (isset($_SESSION['user']) && (cache_get('user', $_SESSION['user']) == session_id())) { $user = user_load($_SESSION['user']); // If user has just been actively been authenticated in the previous request, then we // make it as actively authenticated in this request. if (isset($_SESSION['user_auth_active']) && $_SESSION['user_auth_active']) { $user['auth_active'] = true; unset($_SESSION['user_auth_active']); } } elseif (isset($_COOKIE[_user_autologin_cookie()])) { if (($q == 'login') || ($q == 'logout')) return; user_autologin_verify(); } } /** * Loads user data for a specified user name. * * @param string $uid the name of the user to load * @return mixed data for the specified user, or NULL if the user name does not * exist * @see user_load_from_identity() */ function user_load($uid) { if (store_user_exists($uid)) { $user = store_user_load($uid); $user["uid"] = $uid; if (isset($user["identity"])) { $user["local_identity"] = true; } else { $user["identity"] = simpleid_url('user/' . rawurlencode($uid)); $user["local_identity"] = false; } return $user; } else { return NULL; } } /** * Loads user data for a specified OpenID Identity URI. * * @param string $identity the Identity URI of the user to load * @return mixed data for the specified user, or NULL if the user name does not * exist * @see user_load() */ function user_load_from_identity($identity) { $uid = store_get_uid($identity); if ($uid !== NULL) return user_load($uid); return NULL; } /** * Stores user data for a specified user name. * * @param array $user the user to save */ function user_save($user) { $uid = $user['uid']; store_user_save($uid, $user, array('uid', 'identity', 'pass')); } /** * Attempts to log in a user, using the user name and password specified in the * HTTP request. */ function user_login() { global $user, $GETPOST; // If the user is already logged in, return if (isset($user["uid"])) openid_indirect_response(simpleid_url(), ''); $destination = (isset($GETPOST['destination'])) ? $GETPOST['destination'] : ''; $state = (isset($GETPOST['s'])) ? $GETPOST['s'] : ''; $query = ($state) ? 's=' . rawurlencode($state) : ''; if (isset($_POST['op']) && $_POST['op'] == 'Cancel') { global $version; $request = unpickle($state); $version = openid_get_version($request); if (isset($request['openid.return_to'])) { $return_to = $request['openid.return_to']; $response = simpleid_checkid_error(FALSE); simpleid_assertion_response($response, $return_to); } else { indirect_fatal_error('Login cancelled without a proper OpenID request.'); } return; } // We allow legacy login if the connection is via HTTPS or if SIMPLEID_ALLOW_LEGACY_LOGIN is true $allow_legacy_login = (is_https() || SIMPLEID_ALLOW_LEGACY_LOGIN); if (!isset($_POST['name'])) $_POST['name'] = ''; if (!isset($_POST['pass'])) $_POST['pass'] = ''; if (!isset($_POST['digest'])) $_POST['digest'] = ''; if ( ($_POST['name'] == '') || ( ($allow_legacy_login && ($_POST['pass'] == '') && ($_POST['digest'] == '')) || (!$allow_legacy_login && ($_POST['digest'] == '')) ) ) { if (isset($_POST['destination'])) { // User came from a log in form. set_message('You need to supply the user name and the password in order to log in.'); } if (isset($_POST['nonce'])) cache_delete('user-nonce', $_POST['nonce']); user_login_form($destination, $state); return; } if (!isset($_POST['nonce'])) { if (isset($_POST['destination'])) { // User came from a log in form. set_message('You seem to be attempting to log in from another web page. You must use this page to log in.'); } user_login_form($destination, $state); return; } $time = strtotime(substr($_POST['nonce'], 0, 20)); // Some old versions of PHP does not recognise the T in the ISO 8601 date. We may need to convert the T to a space if (($time == -1) || ($time === FALSE)) $time = strtotime(strtr(substr($_POST['nonce'], 0, 20), 'T', ' ')); if (!cache_get('user-nonce', $_POST['nonce'])) { log_warn('Login attempt: Nonce ' . $_POST['nonce'] . ' not issued or is being reused.'); set_message('SimpleID detected a potential security attack on your log in. Please log in again.'); user_login_form($destination, $state); return; } elseif ($time < time() - SIMPLEID_LOGIN_NONCE_EXPIRES_IN) { log_notice('Login attempt: Nonce ' . $_POST['nonce'] . ' expired.'); set_message('The log in page has expired. Please log in again.'); user_login_form($destination, $state); return; } else { cache_delete('user-nonce', $_POST['nonce']); } if (store_user_verify_credentials($_POST['name'], $_POST, $allow_legacy_login) === false) { set_message('The user name or password is not correct.'); user_login_form($destination, $state); return; } // Set the current authentication time $test_user = user_load($_POST['name']); $test_user['auth_time'] = time(); user_save($test_user); // Set user has been actively authenticated this and the next request only $test_user['auth_active'] = true; $_SESSION['user_auth_active'] = true; _user_login($test_user); log_info('Login successful: ' . $test_user['uid'] . '['. gmstrftime('%Y-%m-%dT%H:%M:%SZ', $test_user['auth_time']) . ']'); if (isset($_POST['autologin']) && ($_POST['autologin'] == 1)) user_autologin_create(); openid_indirect_response(simpleid_url($destination, $query), ''); } /** * Sets the user specified by the parameter as the active user. * * @param array $login_user the user to log in * */ function _user_login($login_user) { global $user; $user = $login_user; $_SESSION['user'] = $login_user['uid']; cache_set('user', $login_user['uid'], session_id()); } /** * Attempts to log out a user and returns to the login form. * * @param string $destination the destination value to be included in the * login form */ function user_logout($destination = NULL) { global $user, $GETPOST; $state = (isset($GETPOST['s'])) ? $GETPOST['s'] : ''; if ($destination == NULL) { if (isset($GETPOST['destination'])) { $destination = $GETPOST['destination']; } else { $destination = ''; } } _user_logout(); set_message('You have been logged out.'); user_login_form($destination, $state); } /** * Logs out the user by deleting the relevant session information. */ function _user_logout() { global $user; user_autologin_invalidate(); session_destroy(); cache_delete('user', $user['uid']); unset($_SESSION['user']); $user = NULL; } /** * Displays a user login form. * * @param string $destination the SimpleID location to which the user is directed * if login is successful * @param string $state the current SimpleID state, if required by the location */ function user_login_form($destination = '', $state = NULL) { global $xtpl; if ($state) { $xtpl->assign('state', htmlspecialchars($state, ENT_QUOTES, 'UTF-8')); $xtpl->parse('main.login.state'); } cache_gc(SIMPLEID_LOGIN_NONCE_EXPIRES_IN, 'user-nonce'); $nonce = openid_nonce(); cache_set('user-nonce', $nonce, 1); $base_path = get_base_path(); $xtpl->assign('javascript', ''); $security_class = (SIMPLEID_ALLOW_AUTOCOMPLETE) ? 'allow-autocomplete ' : ''; if (is_https()) { $security_class .= 'secure'; $xtpl->assign('security_message', 'Secure login using HTTPS.'); } else { if (!SIMPLEID_ALLOW_LEGACY_LOGIN) { $security_class .= 'unsecure login-digest'; $xtpl->assign('security_message', 'Your SimpleID configuration does not allow you to log in unsecurely. Please enable JavaScript and try again, or see the SimpleID documentation for more details.'); $xtpl->assign('security_disabled', 'disabled="disabled"'); } else { $security_class .= 'unsecure login-digest'; $xtpl->assign('security_message', 'WARNING: Your password will be sent to SimpleID as plain text.'); } } $xtpl->assign('security_class', $security_class); extension_invoke_all('user_login_form', $destination, $state); header('X-Frame-Options: DENY'); $xtpl->assign('title', 'Log In'); $xtpl->assign('page_class', 'dialog-page'); $xtpl->assign('destination', htmlspecialchars($destination, ENT_QUOTES, 'UTF-8')); $xtpl->assign('nonce', htmlspecialchars($nonce, ENT_QUOTES, 'UTF-8')); $xtpl->parse('main.login'); $xtpl->parse('main.framekiller'); $xtpl->parse('main'); $xtpl->out('main'); } /** * Returns the user's public page. * * @param string $uid the user ID */ function user_public_page($uid = NULL) { global $xtpl, $user; $xtpl->assign('title', 'User Page'); if ($uid == NULL) { header('HTTP/1.1 400 Bad Request'); set_message('No user specified.'); } else { $user = user_load($uid); if ($user == NULL) { header('HTTP/1.1 404 Not Found'); set_message('User ' . htmlspecialchars($uid, ENT_QUOTES, 'UTF-8') . ' not found.'); } else { header('Vary: Accept'); $content_type = negotiate_content_type(array('text/html', 'application/xml', 'application/xhtml+xml', 'application/xrds+xml')); if ($content_type == 'application/xrds+xml') { user_xrds($uid); return; } else { header('X-XRDS-Location: ' . simpleid_url('xrds/' . rawurlencode($uid))); set_message('This is the user ' . htmlspecialchars($uid, ENT_QUOTES, 'UTF-8') . '\'s SimpleID page. It contains hidden information for the use by OpenID consumers.'); $xtpl->assign('title', htmlspecialchars($uid, ENT_QUOTES, 'UTF-8')); $xtpl->assign('provider', htmlspecialchars(simpleid_url(), ENT_QUOTES, 'UTF-8')); $xtpl->assign('xrds', htmlspecialchars(simpleid_url('xrds/' . rawurlencode($uid)), ENT_QUOTES, 'UTF-8')); if ($user["local_identity"]) { $xtpl->assign('local_id', htmlspecialchars($user["identity"], ENT_QUOTES, 'UTF-8')); } } } } $xtpl->parse('main.provider'); if ($user["local_identity"]) $xtpl->parse('main.local_id'); $xtpl->parse('main'); $xtpl->out('main'); } /** * Returns the public page for a private personal ID. */ function user_ppid_page($ppid = NULL) { global $xtpl; header('Vary: Accept'); $content_type = negotiate_content_type(array('text/html', 'application/xml', 'application/xhtml+xml', 'application/xrds+xml')); if (($content_type == 'application/xrds+xml') || ($_GET['format'] == 'xrds')) { header('Content-Type: application/xrds+xml'); header('Content-Disposition: inline; filename=yadis.xml'); $xtpl->assign('simpleid_base_url', htmlspecialchars(simpleid_url(), ENT_QUOTES, 'UTF-8')); $xtpl->parse('xrds.user_xrds'); $xtpl->parse('xrds'); $xtpl->out('xrds'); return; } else { header('X-XRDS-Location: ' . simpleid_url('ppid/' . rawurlencode($ppid), 'format=xrds')); $xtpl->assign('title', 'Private Personal Identifier'); set_message('This is a private personal identifier.'); $xtpl->parse('main'); $xtpl->out('main'); } } /** * Returns the user's public XRDS page. * * @param string $uid the user ID */ function user_xrds($uid) { global $xtpl; $user = user_load($uid); if ($user != NULL) { header('Content-Type: application/xrds+xml'); header('Content-Disposition: inline; filename=yadis.xml'); if (($user != NULL) && ($user["local_identity"])) { $xtpl->assign('local_id', htmlspecialchars($user["identity"], ENT_QUOTES, 'UTF-8')); $xtpl->parse('xrds.user_xrds.local_id'); $xtpl->parse('xrds.user_xrds.local_id2'); } $xtpl->assign('simpleid_base_url', htmlspecialchars(simpleid_url(), ENT_QUOTES, 'UTF-8')); $xtpl->parse('xrds.user_xrds'); $xtpl->parse('xrds'); $xtpl->out('xrds'); } else { header('HTTP/1.1 404 Not Found'); set_message('User ' . htmlspecialchars($uid, ENT_QUOTES, 'UTF-8') . ' not found.'); $xtpl->parse('main'); $xtpl->out('main'); } } /** * Set up the user section in the header, showing the currently logged in user. * * @param string $state the SimpleID state to retain once the user has logged out, * if required. */ function user_header($state = NULL) { global $user; global $xtpl; if ($user != NULL) { $xtpl->assign('uid', htmlspecialchars($user['uid'], ENT_QUOTES, 'UTF-8')); $xtpl->assign('identity', htmlspecialchars($user['identity'], ENT_QUOTES, 'UTF-8')); if ($state != NULL) { $xtpl->assign('url', htmlspecialchars(simpleid_url('logout', 'destination=continue&s=' . rawurlencode($state), true))); $xtpl->assign('logout', 'Log out and log in as a different user'); } else { $xtpl->assign('url', htmlspecialchars(simpleid_url('logout', '', true))); $xtpl->assign('logout', 'Log out'); } $xtpl->parse('main.user.logout'); $xtpl->parse('main.user'); } } /** * Verfies a log in name and digest using digest authentication. * * @param string $digest the digest supplied by the user * @param string $nonce the nonce supplied by SimpleID in the initial login * form * @param mixed $test_user the claimed user, against which to test the user's * credentials * @return bool true if the verification is successful */ function _user_verify_digest($digest, $nonce, $test_user) { $test_digest1 = md5($test_user['uid'] . ':' . $test_user['pass']); $test_digest = md5($nonce . ':' . $test_digest1); return ($digest == $test_digest); } /** * Creates a auto login cookie. The login cookie will be based on the * current log in user. * * @param string $id the ID of the series of auto login cookies, Cookies * belonging to the same user and computer have the same ID. If none is specified, * one will be generated * @param int $expires the time at which the cookie will expire. If none is specified * the time specified in {@link SIMPLEID_USER_AUTOLOGIN_EXPIRES_IN} will be * used * */ function user_autologin_create($id = NULL, $expires = NULL) { global $user; if ($expires == NULL) { log_debug('Automatic login token created for ' . $user['uid']); } else { log_debug('Automatic login token renewed for ' . $user['uid']); } if ($id == NULL) $id = get_form_token(mt_rand()); if ($expires == NULL) $expires = time() + SIMPLEID_USER_AUTOLOGIN_EXPIRES_IN; $token = get_form_token(mt_rand()); cache_set('autologin-'. md5($user['uid']), $id, array('token' => $token, 'expires' => $expires, 'ip' => $_SERVER['REMOTE_ADDR'])); setcookie(_user_autologin_cookie(), $user['uid'] . ':' . $id . ':' . $token, $expires); } /** * Verifies a auto login cookie. If valid, log in the user automatically. */ function user_autologin_verify() { $cookie = $_COOKIE[_user_autologin_cookie()]; list($uid, $id, $token) = explode(':', $cookie); log_debug('Automatic login token detected for ' . $uid); cache_gc(SIMPLEID_USER_AUTOLOGIN_EXPIRES_IN, 'autologin-' . md5($uid)); $cache = cache_get('autologin-' . md5($uid), $id); if (!$cache) { // Cookie doesn't exist log_notice('Automatic login: Token does not exist on server'); return; } if ($cache['expires'] < time()) { // Cookie expired log_notice('Automatic login: Token on server expired'); return; } if ($cache['token'] != $token) { log_warn('Automatic login: Token on server does not match'); // Token not the same - panic cache_gc(0, 'autologin-' . md5($uid)); user_autologin_invalidate(); return; } // Load the user, tag it as an auto log in $user = user_load($uid); if ($user != NULL) { log_debug('Automatic login token accepted for ' . $uid); $user['autologin'] = TRUE; _user_login($user); // Renew the token user_autologin_create($id, $cache['expires']); } else { log_warn('Automatic login token accepted for ' . $uid . ', but no such user exists'); } } /** * Removes the auto login cookie from the user agent and the SimpleID * cache. */ function user_autologin_invalidate() { if (isset($_COOKIE[_user_autologin_cookie()])) { $cookie = $_COOKIE[_user_autologin_cookie()]; list($uid, $id, $token) = explode(':', $cookie); cache_delete('autologin-' . md5($uid), $id); setcookie(_user_autologin_cookie(), "", time() - 3600); } } /** * Get the name of the auto login cookie. * * @return string the name of the persistent login cookie. */ function _user_autologin_cookie() { return "autologin-" . md5(SIMPLEID_BASE_URL); } ?> simpleid/www/openid.inc0000644000175000017500000011336511710103700014732 0ustar danieldaniel * James Walker * * Copyright (C) Rowan Kerr and James Walker * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: openid.inc 468 2011-12-02 12:14:37Z kmo $ */ /** * OpenID related functions. * * @package simpleid * @filesource */ include_once "bignum.inc"; include_once "random.inc"; /** * OpenID default modulus for Diffie-Hellman key exchange. * * @link http://openid.net/specs/openid-authentication-1_1.html#pvalue, http://openid.net/specs/openid-authentication-2_0.html#pvalue */ define('OPENID_DH_DEFAULT_MOD', '155172898181473697471232257763715539915724801'. '966915404479707795314057629378541917580651227423698188993727816152646631'. '438561595825688188889951272158842675419950341258706556549803580104870537'. '681476726513255747040765857479291291572334510643245094715007229621094194'. '349783925984760375594985848253359305585439638443'); /** * OpenID default generator for Diffie-Hellman key exchange. */ define('OPENID_DH_DEFAULT_GEN', '2'); /** Constant for the global variable {@link $version} */ define('OPENID_VERSION_2', 2); /** Constant for the global variable {@link $version} */ define('OPENID_VERSION_1_1', 1); /** Constant for OpenID namespace */ define('OPENID_NS_2_0', 'http://specs.openid.net/auth/2.0'); /** Constant for OpenID namespace */ define('OPENID_NS_1_1', 'http://openid.net/signon/1.1'); /** Constant for OpenID namespace */ define('OPENID_NS_1_0', 'http://openid.net/signon/1.0'); /** * Constant for the OP-local identifier which indicates that SimpleID should choose an identifier * * @link http://openid.net/specs/openid-authentication-2_0.html#anchor27 */ define('OPENID_IDENTIFIER_SELECT', 'http://specs.openid.net/auth/2.0/identifier_select'); /** Constant for the XRDS service type for return_to verification */ define('OPENID_RETURN_TO', 'http://specs.openid.net/auth/2.0/return_to'); /** Parameter for {@link openid_indirect_response_url()} */ define('OPENID_RESPONSE_QUERY', 0); /** Parameter for {@link openid_indirect_response_url()} */ define('OPENID_RESPONSE_FRAGMENT', 1); /** * A mapping of Type URIs of OpenID extnesions to aliases provided in an OpenID * request. * * @global array $openid_ns_to_alias */ $openid_ns_to_alias = array("http://openid.net/extensions/sreg/1.1" => "sreg"); // For sreg 1.0 compatibility /** * Detects the OpenID version of the current request * * @param mixed $request the OpenID request * @param string $key the key to look for to determine the OpenID * version * @return float either OPENID_VERSION_2 or OPENID_VERSION_1_1 * @see $version * */ function openid_get_version($request, $key = 'openid.ns') { if (!isset($request[$key])) return OPENID_VERSION_1_1; if ($request[$key] != OPENID_NS_2_0) return OPENID_VERSION_1_1; return OPENID_VERSION_2; } /** * Creates a OpenID message for direct response. * * The response will be encoded using Key-Value Form Encoding. * * @param array $data the data in the response * @param float $version the message version * @return string the message in key-value form encoding * @link http://openid.net/specs/openid-authentication-1_1.html#anchor32, http://openid.net/specs/openid-authentication-2_0.html#kvform */ function openid_direct_message($data, $version = OPENID_VERSION_2) { $message = ''; $ns = ''; switch ($version) { case OPENID_VERSION_2: $ns = OPENID_NS_2_0; break; } if (($ns != '') && !isset($data['ns'])) $data['ns'] = $ns; foreach ($data as $key => $value) { if (strpos($key, ':') !== false) { return null; } if (strpos($key, "\n") !== false) { return null; } if (strpos($value, "\n") !== false) { return null; } $message .= "$key:$value\n"; } return $message; } /** * Sends a direct response. * * @param string $message an OpenID message encoded using Key-Value Form * @param string $status the HTTP status to send */ function openid_direct_response($message, $status = '200 OK') { header("HTTP/1.1 $status"); header("Content-Type: text/plain"); print $message; } /** * Creates a OpenID message for indirect response. * * The response will be encoded using HTTP Encoding. * * @param array $data the data in the response * @param float $version the message version * @return array the message * @link http://openid.net/specs/openid-authentication-2_0.html#indirect_comm */ function openid_indirect_message($data, $version = OPENID_VERSION_2) { $ns = ''; switch ($version) { case OPENID_VERSION_2: $ns = OPENID_NS_2_0; break; } if (($ns != '') && !isset($data['openid.ns'])) $data['openid.ns'] = $ns; return $data; } /** * Sends an indirect response to a URL. * * The indirect message is encoded in the URL and returned to the user agent using * a HTTP redirect response. The message can be encoded in either the query component * or the fragment component of the URL. * * @param string $url the URL to which the response is to be sent * @param array|string $message an OpenID message, which can either be an array of keys * and values, or a URL-encoded query string * @param int $component the component of the URL in which the indirect message is * encoded, either OPENID_RESPONSE_QUERY or OPENID_RESPONSE_FRAGMENT */ function openid_indirect_response($url, $message, $component = OPENID_RESPONSE_QUERY) { header('Status: 303 See Other'); header('Location: ' . openid_indirect_response_url($url, $message, $component)); exit; } /** * Encodes an indirect message into a URL * * @param string $url the URL to which the response is to be sent * @param array|string $message an OpenID message, which can either be an array of keys * and values, or a URL-encoded query string * @param int $component the component of the URL in which the indirect message is * encoded, either OPENID_RESPONSE_QUERY or OPENID_RESPONSE_FRAGMENT * @return string the URL to which the response is to be sent, with the * encoded message */ function openid_indirect_response_url($url, $message, $component = OPENID_RESPONSE_QUERY) { // 1. Firstly, get the query string $query = ''; if (is_array($message)) { $query = openid_urlencode_message($message); } else { $query = $message; } // 2. If there is no query string, then we just return the URL if (!$query) return $url; // 3. The URL may already have a query and a fragment. If this is so, we // need to slot in the new query string properly. We disassemble and // reconstruct the URL. $parts = parse_url($url); $url = $parts['scheme'] . '://'; if (isset($parts['user'])) { $url .= $parts['user']; if (isset($parts['pass'])) $url .= ':' . $parts['pass']; $url .= '@'; } $url .= $parts['host']; if (isset($parts['port'])) $url .= ':' . $parts['port']; if (isset($parts['path'])) $url .= $parts['path']; if (($component == OPENID_RESPONSE_QUERY) || (strpos($url, '#') === FALSE)) { $url .= '?' . ((isset($parts['query'])) ? $parts['query'] . '&' : '') . $query; if (isset($parts['fragment'])) $url .= '#' . $parts['fragment']; } elseif ($component == OPENID_RESPONSE_FRAGMENT) { // In theory $parts['fragment'] should be an empty string, but the // current draft specification does not prohibit putting other things // in the fragment. if (isset($parts['query'])) { $url .= '?' . $parts['query'] . '#' . $parts['fragment'] . '&' . $query; } else { $url .= '#' . $parts['fragment'] . '?' . $query; } } return $url; } /** * Encodes a message in application/x-www-form-urlencoded format. * * @param array $message the OpenID message to encode * @return string the encoded message * @since 0.8 */ function openid_urlencode_message($message) { $pairs = array(); foreach ($message as $key => $value) { $pairs[] = $key . '=' . rfc3986_urlencode($value); } return implode('&', $pairs); } /** * Sends a direct message indicating an error. This is a convenience function * for {@link openid_direct_response()}. * * @param string $error the error message * @param array $additional any additional data to be sent with the error * message * @param float $version the message version */ function openid_direct_error($error, $additional = array(), $version = OPENID_VERSION_2) { $message = openid_direct_message(array_merge(array('error' => $error), $additional), $version); openid_direct_response($message, '400 Bad Request'); } /** * Sends an indirect message indicating an error. This is a convenience function * for {@link openid_indirect_response()}. * * @param string $url the URL to which the error message is to be sent * @param string $error the error message * @param array $additional any additional data to be sent with the error * message * @param float $version the message version * @param int $component the component of the URL in which the indirect message is * encoded, either OPENID_RESPONSE_QUERY or OPENID_RESPONSE_FRAGMENT */ function openid_indirect_error($url, $error, $additional = array(), $version = OPENID_VERSION_2, $component = OPENID_RESPONSE_QUERY) { $message = openid_indirect_message(array_merge(array('openid.mode'=> 'error', 'openid.error' => $error), $additional), $version); openid_indirect_response($url, $message, $component); } /** * Gets the realm from the OpenID request. This is specified differently * depending on the OpenID version. * * @param mixed $request the OpenID request * @param float $version the OpenID version for the message * @return string the realm URI */ function openid_get_realm($request, $version) { if ($version == OPENID_VERSION_1_1) { $realm = $request['openid.trust_root']; } if ($version >= OPENID_VERSION_2) { $realm = $request['openid.realm']; } if (!$realm) { $realm = $request['openid.return_to']; } return $realm; } /** * Parses a direct message. * * @param string $message the direct message to parse * @return array an array containing the parsed key-value pairs * * @since 0.7 */ function openid_parse_direct_message($message) { $data = array(); $items = explode("\n", $message); foreach ($items as $item) { list ($key, $value) = explode(':', $item, 2); $data[$key] = $value; } return $data; } /** * Parses a query string. * * Query strings can be used to receive OpenID indirect messages. * * @param string $query the query string to parse * @return array an array containing the parsed key-value pairs * * @since 0.7 */ function openid_parse_query($query) { $data = array(); if ($query === NULL) return array(); if ($query === '') return array(); $pairs = explode('&', $query); foreach ($pairs as $pair) { list ($key, $value) = explode('=', $pair, 2); $data[$key] = urldecode($value); } return $data; } /** * Fix PHP's handling of request data. PHP changes dots in all request parameters * to underscores when creating the $_GET, $_POST and $_REQUEST arrays. * * This function scans the original query string and POST parameters and fixes * them. */ function openid_fix_request() { // Fix GET parameters if (isset($_SERVER['QUERY_STRING'])) { $get = openid_parse_query($_SERVER['QUERY_STRING']); foreach ($get as $key => $value) { // We strip out array-like identifiers - PHP uses special processing for these if ((strpos($key, '[') !== FALSE) && (strpos($key, ']') !== FALSE)) $key = substr($key, 0, strpos($key, '[')); // Replace special characters with underscore as per PHP processing $php_key = preg_replace('/[ .[\x80-\x9F]/', '_', $key); // See if the PHP key is present; if so, copy and delete if (($key != $php_key) && isset($_GET[$php_key])) { $_GET[$key] = $_GET[$php_key]; $_REQUEST[$key] = $_REQUEST[$php_key]; unset($_GET[$php_key]); unset($_REQUEST[$php_key]); } } } // Fix POST parameters $input = file_get_contents('php://input'); if ($input !== FALSE) { $post = openid_parse_query($input); foreach ($post as $key => $value) { // We strip out array-like identifiers - PHP uses special processing for these if ((strpos($key, '[') !== FALSE) && (strpos($key, ']') !== FALSE)) $key = substr($key, 0, strpos($key, '[')); // Replace special characters with underscore as per PHP processing $php_key = preg_replace('/[ .[\x80-\x9F]/', '_', $key); // See if the PHP key is present; if so, copy and delete if (($key != $php_key) && isset($_POST[$php_key])) { $_POST[$key] = $_POST[$php_key]; $_REQUEST[$key] = $_REQUEST[$php_key]; unset($_POST[$php_key]); unset($_REQUEST[$php_key]); } } } openid_parse_request(array_merge($_GET, $_POST)); } /** * Parses the OpenID request to extract namespace information. * * This function builds a map between namespace aliases and their Type URIs. * * @param array $request the OpenID request */ function openid_parse_request($request) { global $openid_ns_to_alias; foreach ($request as $key => $value) { if (strpos($key, 'openid.ns.') === 0) { $alias = substr($key, 10); $openid_ns_to_alias[$value] = $alias; } } } /** * Determines whether a URL matches a realm. * * A URL matches a realm if: * * 1. The URL scheme and port of the URL are identical to those in the realm. * See RFC 3986, section 3.1 for rules about URI matching. * 2. The URL's path is equal to or a sub-directory of the realm's path. * 3. Either: * (a) The realm's domain contains the wild-card characters "*.", and the * trailing part of the URL's domain is identical to the part of the * realm following the "*." wildcard, or * (b) The URL's domain is identical to the realm's domain * * @param string $url to URL to test * @param string $realm the realm * @return bool true if the URL matches the realm * @since 0.6 */ function openid_url_matches_realm($url, $realm) { $url = parse_url($url); $realm = parse_url($realm); foreach(array('user', 'pass', 'fragment') as $key) { if (array_key_exists($key, $url) || array_key_exists($key, $realm)) return false; } if ($url['scheme'] != $realm['scheme']) return false; if (!isset($url['port'])) $url['port'] = ''; if (!isset($realm['port'])) $realm['port'] = ''; if (($url['port'] != $realm['port'])) return false; if (substr($realm['host'], 0, 2) == '*.') { $realm_re = '/^([^.]+\.)?' . preg_quote(substr($realm['host'], 2)) . '$/i'; } else { $realm_re = '/^' . preg_quote($realm['host']) . '$/i'; } if (!preg_match($realm_re, $url['host'])) return false; if (!isset($url['path'])) $url['path'] = ''; if (!isset($realm['path'])) $realm['path'] = ''; if (substr($realm['path'], -1) == '/') $realm['path'] = substr($realm['path'], 0, -1); if (($url['path'] != $realm['path']) && !preg_match('#^' . preg_quote($realm['path']) . '/.*$#', $url['path'])) return false; return true; } /** * Returns the URL of a relying party endpoint for a specified realm. This URL * is used to discover services associated with the realm. * * If the realm's domain contains the wild-card characters "*.", this is substituted * with "www.". * * @param string $realm the realm * @url string the URL * * @since 0.7 */ function openid_realm_discovery_url($realm) { $parts = parse_url($realm); $host = strtr($parts['host'], array('*.' => 'www.'));; $url = $parts['scheme'] . '://'; if (isset($parts['user'])) { $url .= $parts['user']; if (isset($parts['pass'])) $url .= ':' . $parts['pass']; $url .= '@'; } $url .= $host; if (isset($parts['port'])) $url .= ':' . $parts['port']; if (isset($parts['path'])) $url .= $parts['path']; if (isset($parts['query'])) $url .= '?' . $parts['query']; if (isset($parts['fragment'])) $url .= '#' . $parts['fragment']; return $url; } /** * Verifies a return_to URL against the actual URL of the HTTP request. * * The return_to URL matches if: * * - The URL scheme, authority, and path are the same; and * - Any query parameters that are present in the return_to URL are also present * with the same values in the actual request. * * @param string $return_to the URL specified in the openid.return_to parameter * @param string $actual_url the actual URL requested * @return bool true if the URLs match * * @since 0.7 */ function openid_verify_return_to($return_to, $actual_url) { $expected = parse_url($return_to); $actual = parse_url($actual_url); // Schemes are case insensitive if (strtoupper($expected['scheme']) != strtoupper($actual['scheme'])) return false; // Hosts are case insensitive if (strtoupper($expected['host']) != strtoupper($actual['host'])) return false; if (!isset($expected['port'])) $expected['port'] = ''; if (!isset($actual['port'])) $actual['port'] = ''; if ($expected['port'] != $actual['port']) return false; if (!isset($expected['path'])) $expected['path'] = ''; if (!isset($actual['path'])) $actual['path'] = ''; if ($expected['path'] != $actual['path']) return false; if ($expected['query']) { $expected_query = openid_parse_query($expected['query']); $actual_query = openid_parse_query($actual['query']); foreach ($expected_query as $key => $value) { if (!array_key_exists($key, $actual_query)) return false; if ($value != $actual_query[$key]) return false; } } return true; } /** * Filters an OpenID request to find keys specific to an extension, as specified * by the Type URI. * * For exmaple, if the extension has the Type URI http://example.com/ and the * alias example, this function will return an array of all the keys in the * OpenID request which starts with openid.example * * @param string $ns the Type URI of the extension * @param array $request the OpenID request * @return array the filtered request, with the prefix (in the example above, * openid.example.) stripped in the keys. */ function openid_extension_filter_request($ns, $request) { global $openid_ns_to_alias; if (!isset($openid_ns_to_alias[$ns])) return array(); $alias = $openid_ns_to_alias[$ns]; $return = array(); if (is_array($request)) { foreach ($request as $key => $value) { if ($key == 'openid.' . $alias) { $return['#default'] = $value; } if (strpos($key, 'openid.' . $alias . '.') === 0) { $return[substr($key, strlen('openid.' . $alias . '.'))] = $value; } } } return $return; } /** * Determines whether an extension is present in an OpenID request. * * @param string $ns the Type URI of the extension * @param array $request the OpenID request * @return bool true if the extension is present in the request */ function openid_extension_requested($ns, $request) { global $openid_ns_to_alias; if (!isset($openid_ns_to_alias[$ns])) return false; $alias = $openid_ns_to_alias[$ns]; if (is_array($request)) { foreach ($request as $key => $value) { if ((strpos($key, 'openid.' . $alias . '.') === 0) || (strpos($key, 'openid.' . $alias . '=') === 0)) { return true; } } } return false; } /** * Returns the OpenID alias for an extension, given a Type URI, based on the * alias definitions in the current OpenID request. * * @param string $ns the Type URI * @param bool|string $create whether to create an alias if the Type URI does not already * have an alias in the current OpenID request. If this parameter is a string, * then the string specified is the preferred alias to be created, unless a collision * occurs * @return string the alias, or NULL if the Type URI does not already * have an alias in the current OpenID request and $create is false */ function openid_extension_alias($ns, $create = FALSE) { global $openid_ns_to_alias; static $e = 1; if (isset($openid_ns_to_alias[$ns])) return $openid_ns_to_alias[$ns]; if ($create !== FALSE) { if ($create === TRUE) { $alias = 'e' . $e; $e++; } elseif (is_string($create)) { $used_aliases = array_values($openid_ns_to_alias); $alias = $create; $i = 0; while (in_array($alias, $used_aliases)) { $i++; $alias = $create . $i; } } $openid_ns_to_alias[$ns] = $alias; return $alias; } return NULL; } /* ------- OpenID nonce functions -------------------------------------------- */ /** * Generates a nonce for use in OpenID responses * * @return string an OpenID nonce * @link http://openid.net/specs/openid-authentication-2_0.html#positive_assertions */ function openid_nonce() { return gmstrftime('%Y-%m-%dT%H:%M:%SZ') . bin2hex(random_bytes(4)); } /* ------- Diffie-Hellman Key Exchange functions ----------------------------- */ /** * Returns the association types supported by this server. * * @return array an array containing the association types supported by this server as keys * and an array containing the key size (mac_size) and HMAC function (hmac_func) as * values */ function openid_association_types() { $association_types = array('HMAC-SHA1' => array('mac_size' => 20, 'hmac_func' => '_openid_hmac_sha1')); if (OPENID_SHA256_SUPPORTED) $association_types['HMAC-SHA256'] = array('mac_size' => 32, 'hmac_func' => '_openid_hmac_sha256'); return $association_types; } /** * Returns the association types supported by this server and the version of * OpenID. * * OpenID version 1 supports an empty string as the session type. OpenID version 2 * reqires a session type to be sent. * * @param bool $is_https whether the transport layer encryption is used for the current * connection * @param float $version the OpenID version, either OPENID_VERSION_1_1 and OPENID_VERSION_2 * @return array an array containing the session types supported by this server as keys * and an array containing the hash function (hash_func) as * values */ function openid_session_types($is_https = FALSE, $version = OPENID_VERSION_2) { $session_types = array( 'DH-SHA1' => array('hash_func' => '_openid_sha1'), ); if (OPENID_SHA256_SUPPORTED) $session_types['DH-SHA256'] = array('hash_func' => '_openid_sha256'); if (($version >= OPENID_VERSION_2) && ($is_https == TRUE)) { // Under OpenID 2.0 no-encryption is only allowed if TLS is used $session_types['no-encryption'] = array(); } if ($version == OPENID_VERSION_1_1) $session_types[''] = array(); return $session_types; } /** * Generates the cryptographic values required for responding to association * requests * * This involves generating a key pair for the OpenID provider, then calculating * the shared secret. The shared secret is then used to encrypt the MAC key. * * @param string $mac_key the MAC key, in binary representation * @param string $dh_consumer_public the consumer's public key, in Base64 representation * @param string $dh_modulus modulus - a large prime number * @param string $dh_gen generator - a primitive root modulo * @param string $hash_func the hash function * @return array an array containing (a) dh_server_public - the server's public key (in Base64), and (b) * enc_mac_key encrypted MAC key (in Base64), encrypted using the Diffie-Hellman shared secret */ function openid_dh_server_assoc($mac_key, $dh_consumer_public, $dh_modulus = NULL, $dh_gen = NULL, $hash_func = '_openid_sha1') { // Generate a key pair for the server $key_pair = openid_dh_generate_key_pair($dh_modulus, $dh_gen); // Generate the shared secret $ZZ = openid_dh_shared_secret($dh_consumer_public, $key_pair['private'], $dh_modulus); return array( 'dh_server_public' => $key_pair['public'], 'enc_mac_key' => openid_encrypt_mac_key($ZZ, $mac_key, $hash_func) ); } /** * Complete association by obtaining the session MAC key from the key obtained * from the Diffie-Hellman key exchange * * @param string $enc_mac_key the encrypted session MAC key, in Base64 represnetation * @param string $dh_server_public the server's public key, in Base64 representation * @param string $dh_consumer_private the consumer's private key, in Base64 representation * @param string $dh_modulus modulus, in Base64 representation * @param string $hash_func the hash function * @return string the decrypted session MAC key, in Base64 representation */ function openid_dh_consumer_assoc($enc_mac_key, $dh_server_public, $dh_consumer_private, $dh_modulus = NULL, $hash_func = '_openid_sha1') { // Retrieve the shared secret $ZZ = openid_dh_shared_secret($dh_server_public, $dh_consumer_private, $dh_modulus); // Decode the encrypted MAC key $encrypted_mac_key = base64_decode($enc_mac_key); return openid_encrypt_mac_key($ZZ, $encrypted_mac_key, $hash_func); } /** * Calculates the shared secret for Diffie-Hellman key exchange. * * This is the second step in the Diffle-Hellman key exchange process. The other * party (in OpenID 1.0 terms, the consumer) has already generated the public * key ($dh_consumer_public) and sent it to this party (the server). The Diffie-Hellman * modulus ($dh_modulus) and generator ($dh_gen) have either been sent or previously agreed. * * @param string $their_public the other party's public key, in Base64 representation * @param string $my_private this party's private key, in Base64 representation * @param string $dh_modulus modulus, in Base64 representation * @return resource the shared secret (as a bignum) * * @see openid_dh_generate_key_pair() * @link http://www.ietf.org/rfc/rfc2631.txt RFC 2631 */ function openid_dh_shared_secret($their_public, $my_private, $dh_modulus = NULL) { // Decode the keys $y = _openid_base64_to_bignum($their_public); $x = _openid_base64_to_bignum($my_private); if ($dh_modulus != NULL) { $p = _openid_base64_to_bignum($dh_modulus); } else { $p = bignum_new(OPENID_DH_DEFAULT_MOD); } // Generate the shared secret = their public ^ my private mod p = my public ^ their private mod p $ZZ = bignum_powmod($y, $x, $p); return $ZZ; } /** * Generates a key pair for Diffie-Hellman key exchange. * * @param string $dh_modulus modulus, in Base64 representation * @param string $dh_gen generator, in Base64 representation * @return array an array containing: (a) private - the private key, in Base64 * and (b) public - the public key, in Base64 */ function openid_dh_generate_key_pair($dh_modulus = NULL, $dh_gen = NULL) { if ($dh_modulus != NULL) { $p = _openid_base64_to_bignum($dh_modulus); } else { $p = bignum_new(OPENID_DH_DEFAULT_MOD); } if ($dh_gen != NULL) { $g = _openid_base64_to_bignum($dh_gen); } else { $g = bignum_new(OPENID_DH_DEFAULT_GEN); } // Generate the private key - a random number which is less than p $rand = _openid_dh_rand($p); $x = bignum_add($rand, 1); // Calculate the public key is g ^ private mod p $y = bignum_powmod($g, $x, $p); return array('private' => _openid_bignum_to_base64($x), 'public' => _openid_bignum_to_base64($y)); } /** * Encrypts/decrypts and encodes the MAC key. * * @param resource $ZZ the Diffie-Hellman key exchange shared secret as a bignum * @param string $mac_key a byte stream containing the MAC key * @param string $hash_func the hash function * @return string the encrypted MAC key in Base64 representation */ function openid_encrypt_mac_key($ZZ, $mac_key, $hash_func = '_openid_sha1') { // Encrypt/decrypt the MAC key using the shared secret and the hash function $encrypted_mac_key = _openid_xor($ZZ, $mac_key, $hash_func); // Encode the encrypted/decrypted MAC key $enc_mac_key = base64_encode($encrypted_mac_key); return $enc_mac_key; } /** * Encrypts/decrypts using XOR. * * @param string $key the encryption key as a bignum. This is usually * the shared secret (ZZ) calculated from the Diffie-Hellman key exchange * @param string $plain_cipher the plaintext or ciphertext * @param string $hash_func the hash function * @return string the ciphertext or plaintext */ function _openid_xor($key, $plain_cipher, $hash_func = '_openid_sha1') { $decoded_key = bignum_val($key, 256); $hashed_key = call_user_func($hash_func, $decoded_key); $cipher_plain = ""; for ($i = 0; $i < strlen($plain_cipher); $i++) { $cipher_plain .= chr(ord($plain_cipher[$i]) ^ ord($hashed_key[$i])); } return $cipher_plain; } /** * Generates a random integer, which will be used to derive a private key * for Diffie-Hellman key exchange. The integer must be less than $stop * * @param resource $stop a prime number as a bignum * @return resource the random integer as a bignum */ function _openid_dh_rand($stop) { static $duplicate_cache = array(); // Used as the key for the duplicate cache $rbytes = bignum_val($stop, 256); if (array_key_exists($rbytes, $duplicate_cache)) { list($duplicate, $nbytes) = $duplicate_cache[$rbytes]; } else { if ($rbytes[0] == "\x00") { $nbytes = strlen($rbytes) - 1; } else { $nbytes = strlen($rbytes); } $mxrand = bignum_pow(bignum_new(256), $nbytes); // If we get a number less than this, then it is in the // duplicated range. $duplicate = bignum_mod($mxrand, $stop); if (count($duplicate_cache) > 10) { $duplicate_cache = array(); } $duplicate_cache[$rbytes] = array($duplicate, $nbytes); } do { $bytes = "\x00" . random_bytes($nbytes); $n = bignum_new($bytes, 256); // Keep looping if this value is in the low duplicated range } while (bignum_cmp($n, $duplicate) < 0); return bignum_mod($n, $stop); } /* ------- Arbitary precision arithmetic and conversion functions ------------ */ /** * Converts an arbitary precision integer, encoded in Base64, to a bignum * * @param string $str arbitary precision integer, encoded in Base64 * @return resource the string representation */ function _openid_base64_to_bignum($str) { return bignum_new(base64_decode($str), 256); } /** * Converts a string representation of an integer to an arbitary precision * integer, then converts it to Base64 encoding. * * @param string $str the string representation * @return string the Base64 encoded arbitary precision integer */ function _openid_bignum_to_base64($str) { return base64_encode(bignum_val($str, 256)); } /** * Encode an integer as big-endian signed two's complement binary string. * * @param string $num the binary integer * @return string the signed two's complement binary string * @link http://openid.net/specs/openid-authentication-2_0.html#btwoc */ function _openid_btwoc($num) { return pack('H*', $num); } /* ------- Hash and HMAC functions ------------------------------------------- */ /** * Calculates a signature of an OpenID message * * @param array $data the data in the message * @param array $keys a list of keys in the message to be signed (without the * 'openid.' prefix) * @param string $mac_key the MAC key used to sign the message, in Base64 representation * @param string $hmac_func the HMAC function used in the signing process * @param float $version the OpenID version * @return string the signature encoded in Base64 */ function openid_sign($data, $keys, $mac_key, $hmac_func = '_openid_hmac_sha1', $version = OPENID_VERSION_2) { $signature = ''; $sign_data = array(); foreach ($keys as $key) { if (array_key_exists('openid.' . $key, $data)) { $sign_data[$key] = $data['openid.' . $key]; } } $signature_base_string = _openid_signature_base_string($sign_data, $version); $secret = base64_decode($mac_key); $signature = call_user_func($hmac_func, $secret, $signature_base_string); return base64_encode($signature); } /** * Calculates the base string from which an OpenID signature is generated. * * OpenID versions 1 and 2 specify that messages are to be encoded using Key-Value * Encoding when generating signatures. However, future OpenID version may * specify different ways of encoding the message, such as OAuth. * * @param array $data the data to sign * @param float $version the OpenID version * @return string the signature base string * @link http://openid.net/specs/openid-authentication-2_0.html#anchor11 */ function _openid_signature_base_string($data, $version) { switch ($version) { case OPENID_VERSION_1_1: case OPENID_VERSION_2: // We set OPENID_VERSION_1_1 because we don't want to sign the namespace header $signature_base_string = openid_direct_message($data, OPENID_VERSION_1_1); break; default: // We set OPENID_VERSION_1_1 because we don't want to sign the namespace header $signature_base_string = openid_direct_message($data, OPENID_VERSION_1_1); } return $signature_base_string; } /** * Obtains the SHA1 hash of a string in binary representation. * * @param string $text the text to be hashed * @return string the hash in binary representation */ function _openid_sha1($text) { if (version_compare(PHP_VERSION, '5.0.0', '>=')) { return sha1($text, true); } elseif (function_exists('hash') && function_exists('hash_algos') && (in_array('sha1', hash_algos()))) { return hash('sha1', $text, true); } else { return pack('H*', sha1($text)); } } /** * Obtains the keyed hash value using the HMAC method and the SHA1 algorithm * * @param string $key the key in binary representation * @param string $text the text to be hashed * @return string the hash in binary representation */ function _openid_hmac_sha1($key, $text) { if (function_exists('hash_hmac') && function_exists('hash_algos') && (in_array('sha1', hash_algos()))) { return hash_hmac('sha1', $text, $key, true); } else { if (!defined('OPENID_SHA1_BLOCKSIZE')) define('OPENID_SHA1_BLOCKSIZE', 64); if (strlen($key) > OPENID_SHA1_BLOCKSIZE) { $key = _openid_sha1($key); } $key = str_pad($key, OPENID_SHA1_BLOCKSIZE, chr(0x00)); $ipad = str_repeat(chr(0x36), OPENID_SHA1_BLOCKSIZE); $opad = str_repeat(chr(0x5c), OPENID_SHA1_BLOCKSIZE); $hash1 = _openid_sha1(($key ^ $ipad) . $text); $hmac = _openid_sha1(($key ^ $opad) . $hash1); return $hmac; } } // Check if SHA-256 support is available if (function_exists('hash_hmac') && function_exists('hash_algos') && (in_array('sha256', hash_algos()))) { /** * Whether the current installation of PHP supports SHA256. SHA256 is supported * if the hash module is properly compiled and loaded into PHP. */ define('OPENID_SHA256_SUPPORTED', true); /** * Obtains the SHA256 hash of a string in binary representation. * * @param string $text the text to be hashed * @return string $hash the hash in binary representation */ function _openid_sha256($text) { return hash('sha256', $text, true); } /** * Obtains the keyed hash value using the HMAC method and the SHA256 algorithm * * @param string $key the key in binary representation * @param string $text the text to be hashed * @return string the hash in binary representation */ function _openid_hmac_sha256($key, $text) { return hash_hmac('sha256', $text, $key, true); } } else { /** @ignore */ define('OPENID_SHA256_SUPPORTED', false); } if (!function_exists('rfc3986_urlencode')) { /** * Encodes a URL using RFC 3986. * * PHP's rfc3986_urlencode function encodes a URL using RFC 1738 for PHP versions * prior to 5.3. RFC 1738 has been * updated by RFC 3986, which change the list of characters which needs to be * encoded. * * Strictly correct encoding is required for various purposes, such as OAuth * signature base strings. * * @param string $s the URL to encode * @return string the encoded URL */ function rfc3986_urlencode($s) { if (version_compare(PHP_VERSION, '5.3.0', '>=')) { return rawurlencode($s); } else { return str_replace('%7E', '~', rawurlencode($s)); } } } ?>simpleid/www/upgrade.php0000644000175000017500000002705311710103700015117 0ustar danieldaniel array('upgrade_rp_to_store', 'upgrade_token_to_store') ); /** * This variable holds an instance of the XTemplate engine. * * @global object $xtpl */ $xtpl = NULL; /** * This variable holds the combined $_GET and $_POST superglobal arrays. * This is then passed through {@link openid_fix_request()}. * * @global array $GETPOST */ $GETPOST = array_merge($_GET, $_POST); upgrade_start(); /** * Entry point for SimpleID upgrade script. * * @see user_init() */ function upgrade_start() { global $xtpl, $GETPOST; $xtpl = new XTemplate('html/template.xtpl'); $xtpl->assign('version', SIMPLEID_VERSION); $xtpl->assign('base_path', get_base_path()); $xtpl->assign('css', '@import url(' . get_base_path() . 'html/upgrade.css);'); // Check if the configuration file has been defined if (!defined('SIMPLEID_BASE_URL')) { indirect_fatal_error('No configuration file found. See the manual for instructions on how to set up a configuration file.'); } if (!is_dir(SIMPLEID_IDENTITIES_DIR)) { indirect_fatal_error('Identities directory not found. See the manual for instructions on how to set up SimpleID.'); } if (!is_dir(SIMPLEID_CACHE_DIR) || !is_writeable(SIMPLEID_CACHE_DIR)) { indirect_fatal_error('Cache directory not found or not writeable. See the manual for instructions on how to set up SimpleID.'); } if (!is_dir(SIMPLEID_STORE_DIR) || !is_writeable(SIMPLEID_STORE_DIR)) { indirect_fatal_error('Store directory not found or not writeable. See the manual for instructions on how to set up SimpleID.'); } if ((@ini_get('register_globals') === 1) || (@ini_get('register_globals') === '1') || (strtolower(@ini_get('register_globals')) == 'on')) { indirect_fatal_error('register_globals is enabled in PHP configuration, which is not supported by SimpleID. See the manual for further information.'); } $q = (isset($GETPOST['q'])) ? $GETPOST['q'] : ''; $q = explode('/', $q); extension_init(); user_init(NULL); upgrade_user_init(); $routes = array( 'upgrade-selection' => 'upgrade_selection', 'upgrade-apply' => 'upgrade_apply', '.*' => 'upgrade_info' ); simpleweb_run($routes, implode('/', $q)); } /** * Displays the upgrade info page. */ function upgrade_info() { global $xtpl; $xtpl->assign('token', get_form_token('upgrade_info')); $xtpl->parse('main.upgrade_info'); $xtpl->assign('title', 'Upgrade'); $xtpl->parse('main'); $xtpl->out('main'); } /** * Detects the current installed version of SimpleID, selects the individual upgrade * functions applicable to this upgrade and displays the upgrade * selection page. */ function upgrade_selection() { global $xtpl, $upgrade_access_check; cache_gc(0, 'upgrade'); if (!validate_form_token($_POST['tk'], 'upgrade_info')) { set_message('SimpleID detected a potential security attack. Please try again.'); upgrade_info(); return; } $functions = upgrade_get_functions(); if (count($functions) == 0) { if (!$upgrade_access_check) $xtpl->parse('main.selection.selection_complete.upgrade_access_check'); $xtpl->parse('main.upgrade_selection.selection_complete'); } else { $handle = random_id(); cache_set('upgrade', $handle, $functions); $xtpl->assign('handle', $handle); $xtpl->assign('token', get_form_token('upgrade_selection')); $xtpl->parse('main.upgrade_selection.selection_continue'); } $xtpl->assign('original_version', upgrade_get_version()); $xtpl->assign('this_version', SIMPLEID_VERSION); $xtpl->parse('main.upgrade_selection'); $xtpl->assign('title', 'Upgrade'); $xtpl->parse('main'); $xtpl->out('main'); } /** * Applies the upgrade. */ function upgrade_apply() { global $xtpl, $upgrade_access_check; if (!validate_form_token($_POST['tk'], 'upgrade_selection')) { set_message('SimpleID detected a potential security attack. Please try again.'); upgrade_selection(); return; } $results = ''; $functions = cache_get('upgrade', $_POST['handle']); foreach ($functions as $function) { $results .= call_user_func($function); } if (!$upgrade_access_check) $xtpl->parse('main.upgrade_results.upgrade_access_check'); $xtpl->assign('results', $results); $xtpl->parse('main.upgrade_results'); cache_gc(0, 'upgrade'); $xtpl->assign('title', 'Upgrade'); $xtpl->parse('main'); $xtpl->out('main'); } /** * Detects the current installed version of SimpleID * * The current installed version of SimpleID is taken from the {@link store_get() version} * application setting. This setting is only available for versions 0.7 or later, so * if it is absent we can assume it's prior to version 0.7. * * @return string the detected version, or the string '0.6.0 or earlier' */ function upgrade_get_version() { return store_get('version', '0.6.0 or earlier'); } /** * Sets the current version of SimpleID. * * This function sets the version application setting via {@link store_get()}. * A specific version can be specified, or it can be taken from {@link SIMPLEID_VERSION}. * * @param string $version the version to set */ function upgrade_set_version($version = NULL) { if ($version == NULL) $version = SIMPLEID_VERSION; store_set('version', $version); } /** * Selects the upgrade functions applicable for this upgrade. * * The upgrade functions are specified by the {@link $upgrade_functions} * variable. This variable is an associative array containing version numbers * as keys and an array of upgrade function names as values. This function * merges all the upgrade function names of the version between the current * installed version and the upgraded version. * * @param string $version the version of SimpleID to upgrade from, calls * {@link upgrade_get_version()} if not specified * @return array an array of strings, containing the list of upgrade functions * to call. The functions should be called in the same order as they appear * in this array * */ function upgrade_get_functions($version = NULL) { global $upgrade_functions; if ($version == NULL) $version = upgrade_get_version(); $functions = array(); uksort($upgrade_functions, '_upgrade_version_reverse_sort'); foreach ($upgrade_functions as $upgrade_version => $upgrades) { if (version_compare($version, $upgrade_version, '<')) { $functions = array_merge($functions, $upgrades); } } if (version_compare($version, SIMPLEID_VERSION, '<')) $functions[] = 'upgrade_set_version'; return $functions; } /** * Callback function for uksort() to reverse sort version numbers. * * @param string $a * @param string $b * @return int */ function _upgrade_version_reverse_sort($a, $b) { return -version_compare($a, $b); } /** * Determines whether the current user has permission to run this script. * * A user has permission to run this script if: * * - administrator=1 appears in the user's identity file; or * - {@link $upgrade_access_check} is false * * If the user does not have permission, {@link upgade_access_denied()} is called */ function upgrade_user_init() { global $user, $upgrade_access_check; if ($upgrade_access_check) { if (($user == NULL) || ($user['administrator'] != 1)) upgrade_access_denied(); } } /** * Displays a page notifying the user that he or she does not have permission to * run the upgrade script. */ function upgrade_access_denied() { global $xtpl; $xtpl->parse('main.upgrade_access_denied'); $xtpl->assign('title', 'Access Denied'); $xtpl->parse('main'); $xtpl->out('main'); exit; } /* ------------------------------------------------------------------------------------------------------- */ /** * Moves the user's site preferences from the cache to the store. * * @since 0.7 */ function upgrade_rp_to_store() { $dir = opendir(SIMPLEID_IDENTITIES_DIR); while (($file = readdir($dir)) !== false) { $filename = SIMPLEID_IDENTITIES_DIR . '/' . $file; if ((filetype($filename) != "file") || (!preg_match('/^(.+)\.identity$/', $file, $matches))) continue; $uid = $matches[1]; $user = user_load($uid); $rp = cache_get('rp', $uid); if ($rp != NULL) { $user['rp'] = $rp; user_save($user); cache_delete('rp', $uid); } } } /** * Moves the site token from the cache to the store. * * @since 0.7 */ function upgrade_token_to_store() { $site_token = cache_get('token', SIMPLEID_BASE_URL); if ($site_token != NULL) { store_set('site-token', $site_token); cache_delete('token', SIMPLEID_BASE_URL); } } ?> simpleid/www/page.inc0000644000175000017500000002134411710103700014363 0ustar danieldanielassign('blocks', implode($blocks)); $xtpl->parse('main.blocks'); $xtpl->assign('title', 'Dashboard'); $xtpl->parse('main'); $xtpl->out('main'); } /** * Displays the profile page. */ function page_profile() { global $user; global $xtpl; if ($user == NULL) { user_login_form('my/profile'); return; } user_header(); page_nav(); $blocks = _page_discovery_block(); $blocks = array_merge($blocks, extension_invoke_all('page_profile')); $blocks = array_map('page_render_block', $blocks); $xtpl->assign('blocks', implode($blocks)); $xtpl->parse('main.blocks'); $xtpl->assign('javascript', ''); $xtpl->assign('title', 'My Profile'); $xtpl->parse('main'); $xtpl->out('main'); } /** * Returns the user's home page. */ function page_sites() { global $user; global $xtpl; if ($user == NULL) { user_login_form('my/sites'); return; } user_header(); page_nav(); if (isset($user['rp'])) { $user_rps =& $user['rp']; } else { $user_rps = array(); } if (isset($_POST['tk'])) { if (!validate_form_token($_POST['tk'], 'autorelease')) { set_message('SimpleID detected a potential security attack. Please try again.'); } else { if (isset($_POST['autorelease'])) { foreach ($_POST['autorelease'] as $realm => $autorelease) { if (isset($user_rps[$realm])) { $user_rps[$realm]['auto_release'] = ($autorelease) ? 1 : 0; } } } if (isset($_POST['remove'])) { foreach ($_POST['remove'] as $realm => $autorelease) { if (isset($user_rps[$realm])) { unset($user_rps[$realm]); } } } if (isset($_POST['update-all'])) { foreach ($user_rps as $realm => $values) { $user_rps[$realm]['auto_release'] = (isset($_POST['autorelease'][$realm]) && $_POST['autorelease'][$realm]) ? 1 : 0; } } user_save($user); set_message('Your preferences have been saved.'); } } if ($user_rps) { foreach ($user_rps as $realm => $rp) { $xtpl->assign('realm', htmlspecialchars($rp['realm'], ENT_QUOTES, 'UTF-8')); $xtpl->assign('last_time', htmlspecialchars($rp['last_time'], ENT_QUOTES, 'UTF-8')); $xtpl->assign('last_time_formatted', htmlspecialchars(strftime(SIMPLEID_DATE_TIME_FORMAT, $rp['last_time']), ENT_QUOTES, 'UTF-8')); $xtpl->assign('auto_release', (isset($rp['auto_release']) && $rp['auto_release']) ? 'checked="checked"' : ''); if (SIMPLEID_VERIFY_RETURN_URL_USING_REALM) { // $rp_info would usually expire by now, so we allow for stale results to be retrieved to improve performance $rp_info = simpleid_get_rp_info($realm, TRUE); if (!isset($rp_info['return_to_verified']) || !$rp_info['return_to_verified']) $xtpl->assign('realm_class', 'return-to-suspect'); } $xtpl->parse('main.sites.realm'); } } if (!$user_rps || (count($user_rps) == 0)) { $xtpl->assign('disabled', 'disabled="disabled"'); } $xtpl->assign('token', get_form_token('autorelease')); $xtpl->parse('main.sites'); $xtpl->assign('title', 'My Sites'); $xtpl->assign('javascript', ''); $xtpl->parse('main'); $xtpl->out('main'); } /** * Set up the navigation section in the header */ function page_nav() { global $user; global $xtpl; $xtpl->assign('nav_base', trim(simpleid_url(' ', '', true))); if ($user != NULL) { if (isset($user['administrator']) && ($user['administrator'] == 1)) $xtpl->parse('main.nav.nav_admin'); } $xtpl->parse('main.nav'); } /** * Renders a particular block. * * @param array $block the block to render * @return string the HTML of the rendered block */ function page_render_block($block) { static $xtpl_block; if (!$xtpl_block) $xtpl_block = new XTemplate('html/block.xtpl'); $xtpl_block->reset('block'); $xtpl_block->assign('id', $block['id']); $xtpl_block->assign('title', $block['title']); $xtpl_block->assign('content', $block['content']); if (isset($block['links'])) { $xtpl_block->assign('links', $block['links']); $xtpl_block->parse('block.links'); } $xtpl_block->parse('block'); return $xtpl_block->text('block'); } /** * Returns the welcome block. * * @return array the welcome block */ function _page_welcome_block() { global $user; return array(array( 'id' => 'welcome', 'title' => 'Welcome', 'content' => 'You are logged in as ' . htmlspecialchars($user['uid'], ENT_QUOTES, 'UTF-8') . ' (' . htmlspecialchars($user['identity'], ENT_QUOTES, 'UTF-8') . ').' )); } function _page_discovery_block() { global $user; $html = "

<link> tags

"; $html .= "
"; $html .= ""; $html .= "
"; $html .= ""; $html .= "\n"; $html .= "

YADIS

"; $html .= "
  1. Write your own or download your YADIS document
  2. "; $html .= "
  3. Add HTTP headers or <meta> tag, e.g.:
    <meta http-equiv="X-XRDS-Location" content="" . htmlspecialchars(simpleid_url('xrds/'. $user['uid']), ENT_QUOTES, 'UTF-8') . "" />
    "; $html .= "
"; return array(array( 'id' => 'discovery', 'title' => 'Claim your Identifier', 'content' => $html, 'links' => 'More information' )); } ?> simpleid/www/html/0000755000175000017500000000000011746513235013735 5ustar danieldanielsimpleid/www/html/upgrade.css0000644000175000017500000000040611710103700016055 0ustar danieldaniel.upgrade-version { font-weight: bold; font-size: 1.5em; } .original-version { color: #666666; } .this-version { color: #4A80ED; } .upgrade-results { overflow: auto; height: 200px; border: 1px solid #666666; background-color: #EEEEEE; } simpleid/www/html/md5.js0000644000175000017500000002057311710103700014746 0ustar danieldaniel/* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for more info. */ /* * Configurable variables. You may need to tweak these to be compatible with * the server-side, but the defaults work in most cases. */ var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ /* * These are the functions you'll usually want to call * They take string arguments and return either hex or base-64 encoded strings */ function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));} function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));} function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));} function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); } function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); } function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); } /* * Perform a simple self-test to see if the VM is working */ function md5_vm_test() { return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; } /* * Calculate the MD5 of an array of little-endian words, and a bit length */ function core_md5(x, len) { /* append padding */ x[len >> 5] |= 0x80 << ((len) % 32); x[(((len + 64) >>> 9) << 4) + 14] = len; var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; for(var i = 0; i < x.length; i += 16) { var olda = a; var oldb = b; var oldc = c; var oldd = d; a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); c = md5_ff(c, d, a, b, x[i+10], 17, -42063); b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); a = safe_add(a, olda); b = safe_add(b, oldb); c = safe_add(c, oldc); d = safe_add(d, oldd); } return Array(a, b, c, d); } /* * These functions implement the four basic operations the algorithm uses. */ function md5_cmn(q, a, b, x, s, t) { return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); } function md5_ff(a, b, c, d, x, s, t) { return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); } function md5_gg(a, b, c, d, x, s, t) { return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); } function md5_hh(a, b, c, d, x, s, t) { return md5_cmn(b ^ c ^ d, a, b, x, s, t); } function md5_ii(a, b, c, d, x, s, t) { return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); } /* * Calculate the HMAC-MD5, of a key and some data */ function core_hmac_md5(key, data) { var bkey = str2binl(key); if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz); var ipad = Array(16), opad = Array(16); for(var i = 0; i < 16; i++) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5C5C5C5C; } var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); return core_md5(opad.concat(hash), 512 + 128); } /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ function safe_add(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } /* * Bitwise rotate a 32-bit number to the left. */ function bit_rol(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)); } /* * Convert a string to an array of little-endian words * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. */ function str2binl(str) { var bin = Array(); var mask = (1 << chrsz) - 1; for(var i = 0; i < str.length * chrsz; i += chrsz) bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); return bin; } /* * Convert an array of little-endian words to a string */ function binl2str(bin) { var str = ""; var mask = (1 << chrsz) - 1; for(var i = 0; i < bin.length * 32; i += chrsz) str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); return str; } /* * Convert an array of little-endian words to a hex string. */ function binl2hex(binarray) { var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var str = ""; for(var i = 0; i < binarray.length * 4; i++) { str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF); } return str; } /* * Convert an array of little-endian words to a base-64 string */ function binl2b64(binarray) { var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var str = ""; for(var i = 0; i < binarray.length * 4; i += 3) { var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16) | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF); for(var j = 0; j < 4; j++) { if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); } } return str; } simpleid/www/html/simpleid.ico0000644000175000017500000001246611710103700016227 0ustar danieldaniel h&  ¨Ž(    fffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿgggÿsssÿoooÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿÿðððÿÿÿÿÿÿÿÿÿïïïÿ———ÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ‚‚‚ÿýýýÿìììÿ¦¦¦ÿ¥¥¥ÿéééÿÿÿÿÿzzzÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ›››ÿãããÿ”””ÿfffÿfffÿ¨¨¨ÿÿÿÿÿ›››ÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿjjjÿšššÿÅÅÅÿúúúÿüüüÿzzzÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ¤¤¤ÿòòòÿÿÿÿÿÿÿÿÿàààÿÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿwwwÿþþþÿíííÿ®®®ÿyyyÿpppÿqqqÿgggÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ|||ÿÿÿÿÿÃÃÃÿlllÿtttÿëëëÿþþþÿnnnÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿÆÆÆÿÿÿÿÿüüüÿÿÿÿÿÿÿÿÿ´´´ÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ‰‰‰ÿ¥¥¥ÿ¢¢¢ÿ‚‚‚ÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ( @   fffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿgggÿgggÿsssÿsssÿoooÿoooÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿgggÿgggÿsssÿsssÿoooÿoooÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿÿÿðððÿðððÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïïïÿïïïÿ———ÿ———ÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿÿÿðððÿðððÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïïïÿïïïÿ———ÿ———ÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ‚‚‚ÿ‚‚‚ÿýýýÿýýýÿìììÿìììÿ¦¦¦ÿ¦¦¦ÿ¥¥¥ÿ¥¥¥ÿéééÿéééÿÿÿÿÿÿÿÿÿzzzÿzzzÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ‚‚‚ÿ‚‚‚ÿýýýÿýýýÿìììÿìììÿ¦¦¦ÿ¦¦¦ÿ¥¥¥ÿ¥¥¥ÿéééÿéééÿÿÿÿÿÿÿÿÿzzzÿzzzÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ›››ÿ›››ÿãããÿãããÿ”””ÿ”””ÿfffÿfffÿfffÿfffÿ¨¨¨ÿ¨¨¨ÿÿÿÿÿÿÿÿÿ›››ÿ›››ÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ›››ÿ›››ÿãããÿãããÿ”””ÿ”””ÿfffÿfffÿfffÿfffÿ¨¨¨ÿ¨¨¨ÿÿÿÿÿÿÿÿÿ›››ÿ›››ÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿjjjÿjjjÿšššÿšššÿÅÅÅÿÅÅÅÿúúúÿúúúÿüüüÿüüüÿzzzÿzzzÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿjjjÿjjjÿšššÿšššÿÅÅÅÿÅÅÅÿúúúÿúúúÿüüüÿüüüÿzzzÿzzzÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ¤¤¤ÿ¤¤¤ÿòòòÿòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàààÿàààÿÿÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ¤¤¤ÿ¤¤¤ÿòòòÿòòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàààÿàààÿÿÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿwwwÿwwwÿþþþÿþþþÿíííÿíííÿ®®®ÿ®®®ÿyyyÿyyyÿpppÿpppÿqqqÿqqqÿgggÿgggÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿwwwÿwwwÿþþþÿþþþÿíííÿíííÿ®®®ÿ®®®ÿyyyÿyyyÿpppÿpppÿqqqÿqqqÿgggÿgggÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ|||ÿ|||ÿÿÿÿÿÿÿÿÿÃÃÃÿÃÃÃÿlllÿlllÿtttÿtttÿëëëÿëëëÿþþþÿþþþÿnnnÿnnnÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ|||ÿ|||ÿÿÿÿÿÿÿÿÿÃÃÃÿÃÃÃÿlllÿlllÿtttÿtttÿëëëÿëëëÿþþþÿþþþÿnnnÿnnnÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿÆÆÆÿÆÆÆÿÿÿÿÿÿÿÿÿüüüÿüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´ÿ´´´ÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿÆÆÆÿÆÆÆÿÿÿÿÿÿÿÿÿüüüÿüüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ´´´ÿ´´´ÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ‰‰‰ÿ‰‰‰ÿ¥¥¥ÿ¥¥¥ÿ¢¢¢ÿ¢¢¢ÿ‚‚‚ÿ‚‚‚ÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿ‰‰‰ÿ‰‰‰ÿ¥¥¥ÿ¥¥¥ÿ¢¢¢ÿ¢¢¢ÿ‚‚‚ÿ‚‚‚ÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿfffÿsimpleid/www/html/openid-consent.js0000644000175000017500000000054511710103700017203 0ustar danieldaniel$(document).ready(function() { $('.return-to-suspect').click(function() { if ($(this).attr('checked') == false) return true; return confirm('This web site has not confirmed its identity and might be fraudulent.\n\nAre you sure you wish to automatically send your information to this site for any future requests?'); }); }); simpleid/www/html/drive.png0000644000175000017500000000053211710103700015533 0ustar danieldaniel‰PNG  IHDRµú7êgAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<ìIDAT(Ï¥‘=JA…¿^{ÖÀ„Å@3o±0“x Oà Ïã œd‡¹ÁF›‚˜‚SÝÕeнƒ‘ÉVPI½÷¾¢Êÿ׌}`Xk­D€ #ÒÝ5àŒa5ïϑɓ·ªèymî;ññŒw+CãS®èÜf5ï|•àˆá8 â„#Z¶{Y_Ô†`%ܦ^ñÉSç…o>1JÂH$ÃsŒà¥AÙà˜¯‘¸BY"µ‰DÅ‘ f—øEIÜHØŒ‘²`NÁÙ¿]ñ?íó­0æÛ!H¹gÆZëöþæ/ˆ6L‘IEND®B`‚simpleid/www/html/simpleid.png0000644000175000017500000000344011710103700016231 0ustar danieldaniel‰PNG  IHDR@@R Ö pHYs  ÒÝ~üÒIDATxœíZ}HTKßrÓR´¤Ré¡ –}b–ÚKSói”ˆ˜)‘EöaFJVJeT&I„‚šX  R†J$~QB=_SÄ>ÔL^ø –iZ®™ïÇÞív÷î½»sw3ûû#Æ3sæ7gfΙsî¦}úôèÑ# 7nÜPüw………8Äððp1xuzz:ÆÍÌÌ;vŒwíÞ¿_TTebbróæMHŽ9òõëW1£ÿd€lØ·o_nn®Øõæº)솂ǰ‰ÁÁÁP»}ûöÎ;ÕGó°ñ¶¶¶îîî u»…ýA?á.éê:tö_Œ@©TÚØØŒ}üøQoû÷ïß¼y³¦ÞÑÑÑÓ§OÓ$$$¸¸¸ ¡R©Ž?Îí"×sÉ’%ìHC`jjÊ6¹a\|Rm keÖ¯_önÜÞªªªû÷ïË"²³³IÃÜÜçAÈ‚(¤¬ÑH€7mÚôƒ‹/NNN²dl”@@RíÒ˜‰ ;o™l»§§‡Æc;ž ˜¢ÐÕ.]ºÔÛÛKIœ|é\Œ×eeeySSÓ­[·è ÌIôÖËË —‡M& 6nÜØØØøòåKz3P0.¿råJ"‹‹£Ìì¤`¤uHRîÞ½ËÊ$®\¹ƒ¼O›•i$ˆŽŽ&)\—K@ÐÝÝ-—àÞ½{l©¼eË–††n/ÎC›ÙŸµ8¬ ­¯¯rvvÞºu+;¬¢¢‚’@R}áÂÒ¶°° á €oK¦{býýý‰‰‰×¯_ìmii‘¬ó%”¸…|¸ò¶¶¶fffإׯ_ãjIN­ÜíÙ³gZÎHC F‚_€ÀÐõ¡að24ŒÌ5ŒÌ5Œ0@:€ìrݺuk×®]¾|ùÂ… ¹½HÏzzz:::Z[[µ)Jµ‡,LLLì!£†šÔŽRO"Am”ŸŸ¯}Î#zvìØ±k×.:]{{{¤£}}}—/_Öé{„:( P_=²Ë‡>~üxrr’+·±± R?(œÉÕ«WQs e]AiÀ¶mÛx’¶¶6R@«cxx¸   ¨¨¯JÅŸÛ·oü¡[KP°`Ážu9 Å·oßjRïæää šS©TS T x?Ÿë JpUxWH©T¦¤¤ 111zçÕ«W(M>þÌóêµ ‚Ò€êêj„ õBPÁˆ¿3à ?|øÐÞÞþâÅ‹çÏŸÏÌÌБ ‚> UVVÖÖÖ— YïÀôô4ùB—ðôôtww_½z5NFRÑÔÔ4ŠÜ·¬¬LÎôóÃ’¿|ŸW©trr‚=kÖ¬AÔפèïï×ç~Նʅs:”——³B??¿°°0î÷W`ÕªU>>>\ãu‚Î,]º4--'?uê”ä{„Ø566Æþ ŽŽŽ?Ï€‘‘ÄWWW®ÐÒÒ266VÓw.=9…®Ë`As…òòò222xßcÝÜÜ`@UU",\‚§‚kƒ´gÏž–‚‰°Ož<¡XxžRSS—-[Æ[å ´ŸjttYœ›Ò‰±ÇxwŽ=jeeE1ž„`ÜFº°…P£ÀwLzìëëëááA>kkü9_SSSWW—^.ôFQ 3ÐËl:ÁXÏ5ŒÌ5ŒÌ5þœñ(ѬÃIEND®B`‚simpleid/www/html/user.png0000644000175000017500000000134511710103700015403 0ustar danieldaniel‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<wIDAT8Ë¥“mHÓQ‡ *éÅÖ¶VÂj)¤¢_ÔOÕÐ¥²9]¬•m*æŒYŠáë–©e-¬¨h–¶¹µ-ÍÐQšJišLËFŸ¤2Á…ä¦L½¿þJŒ™E8\Îï9÷r¸~üþ‡s£·)kùŒé­PóiPòè.I$«ú¯§"EwDtRŸÆÀ]Š[)tÔ$ÒÏÝB„Ì « 4BtTPM…j„‹Ðq1‰…s± ¤M­*¨ánF‡¦ãíj 4ä#/†…‚¸8ÏAö>ºÇPœìïSPŸÎžœùþ S}|뺆ëyŒ=¹çØÌ9{¦Þës×ûÜ”„ö:`ÂÞ÷;3…e©v™q/#Üîó ;„¦uÁûs fEfí ˜q<^ÂýÖ„–Â(„ss±âë7¬(`%šý™|£<ß Ç—iXËD°”%/±X¿ý‰À„ç`ðîŸaòê6.0Ö5 V);©£ãnÇ d¾N>*^¯?ºÁôaW+§ÅjÖza)Zq\ªMó¨ý9=YÏÒ[ ŽZRõ (m§DVžø2Â’®J½‚áò½ó¶bÜÖÚ ¥š2©‰²6‚ÍTØD¢]€HCp°¨¼ÞÉú C<^Áˆ2„8;+‘–­Cu— ’fà5õˆ 7nÄ: ¸e‰éFüè®Â`Q(ñ >%C%Ás2Ù¥¹hidÔÕ3þ@ö› A+Y¥®aUÄ,•©Z¶…1‹<@UZÍÜ%¶Õ±cô_9ñ]œ„f'®É³;ÖìfÐMjë<›W±ý³Uàó7þ ¿Fß©õ²ÚÜ,IEND®B`‚simpleid/www/html/simpleid.css0000644000175000017500000001275211710103700016243 0ustar danieldaniel/* * SimpleID * * Copyright (C) Kelvin Mo 2009 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: simpleid.css 311 2010-06-26 10:53:22Z kmo $ */ body { margin: 0; padding: 0; font: 12px normal Helvetica, Arial, sans-serif; line-height: 1em; } #upgrade-check { background-color: #AA1144; color: #FFFFFF; padding: 5px 10px; text-align: center; display: none; } #upgrade-check p { margin: 0; padding: 0; } #upgrade-check a { color: #FFFFFF; text-decoration: none; border-bottom-color: #FFFFFF; } #header { background-color: #666666; color: #CCCCCC; padding: 5px 10px; } #header h1 { font-weight: bold; font-size: 1.2em; text-transform: uppercase; margin: 0.5em 0; color: #CCCCCC; letter-spacing: 0; } #header h1 a { color: #FFFFFF; text-decoration: none; border-bottom: none; } #logo { float: left; } #nav { background-color: #666666; color: #CCCCCC; padding: 5px 10px; } #nav ul { margin: 0; padding: 0; text-align: left; } #nav li { display: inline; list-style-type: none; } #nav a { background-color: #888888; padding: 6px 8px; border-width: 0; color: #FFFFFF; } #nav ul#nav-left { float: left; } #nav ul#nav-right { float: right; } #footer { margin: 2em 0; padding: 0px 10px; text-align: right; font-size: 0.9em; color: #999999; } #footer address { font-style: normal } #footer a { color: #999999; } #content { margin: 1em 10px; clear: both; } h1 { margin: 1em 0; font-weight: normal; font-size: 1.8em; color: #666666; } h2 { margin: 2em 0; padding-top: 1em; font-weight: normal; font-size: 1.5em; color: #666666; border-top: 2px dotted #BBBBBB; } p, li { line-height: 1.5; } a { border-bottom: 1px solid #CCCCCC; color: #1144AA; text-decoration: none !important; font-weight: bold; } a:visited { border-color: #CCCCCC; color: #114499; } a:focus, a:hover { border-color: #4488EE; color: #4488EE; } table { border-collapse: collapse; margin: 0 0 1em 0; width: 100%; } td, th { border-bottom: 1px solid #CCCCCC; text-align: left; vertical-align: top; padding: 5px 5px; } th { border-bottom: 0px; background-color: #666666; color: #FFFFFF; white-space: nowrap; font-weight: bold; } pre { border:1px solid #CCCCCC; padding: 5px; font-family:"Bitstream Vera Sans Mono","Courier New",monospace; font-size: 0.9em; white-space: nowrap; overflow: scroll; } .realm, .site { padding-left: 20px; background: transparent url(world.png) no-repeat top left; } .app { padding-left: 20px; background: transparent url(application.png) no-repeat top left; } .device { padding-left: 20px; background: transparent url(drive.png) no-repeat top left; } span.last-time { display: none } .message, .login-security { border: 1px solid #666666; padding: 0 10px; background: #DDDDDD; margin-bottom: 10px; } .message p { line-height: 1; } .unsecure { border: 1px solid #AAAA11; background: #FFFFDD; } .unsecure p { padding-left: 20px; background: transparent url(lock-open.png) no-repeat top left; } .secure { border: 1px solid #44AA11; background: #EEFFDD; } .secure p { padding-left: 20px; background: transparent url(lock.png) no-repeat top left; } .user { float: right; margin: 0.5em 0; } .logged-in-as { padding-left: 20px; background: transparent url(user.png) no-repeat top left; } .logged-in-as .identity { color: #FFFFFF; } .logged-in-as a { color: #FFFFFF; border-bottom-color: #FFFFFF; font-weight: normal; } .block { background-color: #EEEEEE; margin-bottom: 20px; } .block-header { background-color: #666666; margin:0 0 5px; padding: 5px 10px; } .block-header h2 { font-size: 1.2em; font-weight: bold; color: #FFFFFF; margin: 0; padding: 0; border-top-width: 0; } .block-header-links { float: right; font-size: 0.9px; text-align: right; white-space: nowrap; } .block-header-links a { color: #FFFFFF; border-bottom-color: #FFFFFF; font-weight: normal; } .block-content { padding: 5px 10px; } .block-content p { margin: 0 0 5px 0; padding: 0; } .block-content h3 { font-size: 1em; font-weight: bold; margin: 0; padding: 5px 0 0 0; } #discovery label { display: inline; } #discovery-templates { display: none; } /* Forms */ .form-item { margin: 1em 0; } label { display: block; font-weight: bold; padding: 2px 0; } label.option { font-weight: normal; } /* Dialogs and dialog pages */ .dialog-page { background: #EEEEEE; } .dialog-page #content { margin: 50px auto; width: 400px; padding: 20px; border: 10px solid #DDDDDD; background: #FFFFFF; } .dialog-page .form-text { width: 100%; } simpleid/www/html/user-login.js0000644000175000017500000000454711710103700016350 0ustar danieldaniel$(document).ready(function() { if (!$('.login-security').is('.allow-autocomplete')) $('#edit-pass').attr('autocomplete', 'off'); if ($('.login-security').is('.login-digest')) { // If we are logging in via digest, we need Javascript to be working $('.login-security').removeClass('unsecure').addClass('secure'); $('.login-security p').html('Secure login using digest. Your password is secured before it is sent to SimpleID.'); $('input:disabled').removeAttr('disabled'); $('form#login-form').submit(function() { $('#edit-submit').attr('disabled', 'disabled'); var user = $('#edit-name').val(); var password = $('#edit-pass').val(); var nonce = $('#edit-nonce').val(); if (password != '') { var digest1 = md5(user + ':' + md5(password)); var digest = md5(nonce + ':' + digest1); } else { var digest = ''; } // Set the digest $('#edit-digest').val(digest); // Set password to nothing $('#edit-pass').val(''); $('#edit-pass').attr('disabled', 'disabled'); return true; }); } $('#edit-name').focus(); }); function utf8_encode(s) { var code; var r = ''; for (var i = 0; i < s.length; i++) { code = s.charCodeAt(i); if (code <= 0x7F) { r += String.fromCharCode(code); } else if (code <= 0x7FF) { r += String.fromCharCode((code >> 6) | 0xC0) + String.fromCharCode((code & 0x3F) | 0x80); } else if ((code <= 0xD7FF) || ((code >= 0xE000) && (code <= 0xFFFF))) { r += String.fromCharCode((code >> 12) | 0xE0) + String.fromCharCode(((code >> 6) & 0x3F) | 0xC0) + String.fromCharCode((code & 0x3F) | 0x80); } else if ((code >= 0xE000) && (code <= 0x10FFFF)) { r += String.fromCharCode((code >> 18) | 0xF0) + String.fromCharCode(((code >> 12) & 0x3F) | 0xE0) + String.fromCharCode(((code >> 6) & 0x3F) | 0xC0) + String.fromCharCode((code & 0x3F) | 0x80); } else { return false; } } return r; } function md5(s) { return hex_md5(utf8_encode(s)); } simpleid/www/html/page-profile.js0000644000175000017500000000140511710103700016624 0ustar danieldanielvar discovery_refresh = function() { var code = ''; if ($('#discovery-openid1')[0].checked) { code += $('#discovery-templates .openid1').html() + '\n'; if ($('#discovery-local-id')[0].checked) code += $('.openid1-local-id').html() + '\n'; } if ($('#discovery-openid2')[0].checked) { code += $('#discovery-templates .openid2').html() + '\n'; if ($('#discovery-local-id')[0].checked) code += $('.openid2-local-id').html() + '\n'; } if (code == '') code = 'You need to set at least one of OpenID 1.x or OpenID 2 to generate the code.'; $('#discovery-link-tags').html(code); } $(document).ready(function() { $('.discovery-checkbox').click(discovery_refresh); discovery_refresh(); }); simpleid/www/html/lock-open.png0000644000175000017500000000132711710103700016314 0ustar danieldaniel‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<iIDAT8Ëu’ËkQ‡¿;i«Ä )R5Öºp­B‚ 7¢+) Š‚a´¡ý¤®Üˆë@@Å… âÊ•¨4¾j³ˆ´h’>¦3÷q\Œ!؇{8Üûñû{”ˆŽjµzÒZ{+Š¢cÀcÌ c̽ ^òŸPi@¥R¹îûþý¡¡!åy+++ÌÍÍI«Õº199ù Зz|(ŸÏO—J%Õh4h6›ø¾O©TRaN—ËåŸõzýqàý)ºÝî«b±èÏÏÏÓl6/A ‚ P‹‹‹—fgg) ù±±±;½ ¼T3ư°°°AõOsjjª´:ŽÌohÈXkÛ{ibbb B‰WWäÙÌQŒSXk9sä ш5ˆIRkûÔuÛOó 9í‰áàµw*Q Âøåc( {title} - SimpleID {javascript}

{title}

{message}

You are being logged into {realm}.

Warning: This web site has not confirmed its identity and might be fraudulent. Do not share any personal information with this web site unless you are sure it is legitimate. See the SimpleID documentation for details (OpenID version 2.0 return_to discovery failure)

{extensions}

Unable to log into {realm}.

Your current identity does not match the requested identity {identity}.

Switch to a different user and try again.

{blocks}
Site Last access Automatic Remove
{realm} {last_time} {last_time_formatted}

Access denied. You are not authorised to access this page. Please log in as an administrator (a user whose identity file includes the line administrator=1).

If you cannot log in, you will have to edit upgrade.php to bypass this access check. To do this:

  1. With a text editor find the upgrade.php file.
  2. There is a line inside your upgrade.php file that says $upgrade_access_check = TRUE;. Change it to $upgrade_access_check = FALSE;.
  3. As soon as the upgrade.php script is done, you must change the file back to its original form with $upgrade_access_check = TRUE;.
  4. To avoid having this problem in future, remember to log in to SimpleID as an administrator before you run this script.

For more detailed information, see the SimpleID documentation.

Use this script to update your installation whenever you upgrade to a new version of SimpleID.

For more detailed information, see the SimpleID documentation.

  1. Back up your installation. This process will change various files within your SimpleID installationand in case of emergency you may need to revert to a backup.
  2. Install your new files in the appropriate location, as described in the SimpleID documentation.

When you have performed the steps above, click Continue.

The version of SimpleID you are updating from has been automatically detected.

Original version: {original_version}

Upgrade version: {this_version}

Your SimpleID installation is up-to-date. This script is complete

Remember to edit upgrade.php to check $upgrade_access_check back to FALSE.

Click Continue to proceed with the upgrade.

Your SimpleID installation has been upgraded. Please check the results below for any errors.

Remember to edit upgrade.php to check $upgrade_access_check back to FALSE.

{results}
xri://$xrds*simple http://specs.openid.net/auth/2.0/signon {simpleid_base_url} {local_id} http://openid.net/signon/1.0 {simpleid_base_url} {local_id} http://specs.openid.net/auth/2.0/server http://simpleid.sourceforge.net/type/version#{version} {uri} {simpleid_base_url} {signature} {acct_uri} {simpleid_user_uri} {local_id} simpleid/www/html/world.png0000644000175000017500000000163311710103700015554 0ustar danieldaniel‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<-IDAT8ËU“Kk\e†Ÿs›3“Ìd2I&ä˜ØJSÚ¦¶15Bš‚ÒÚ ºª(Š`î$ÿB6nÑ"ˆ4 U») BKµj­)¦$iRBÛ0©iK.fƙɜdΜË÷ÏM+é»|yxx7¯¦”bgÆ&GG€#@0*0¥"uæÓ‘³—vòÚcÁØä¨ L§_Ë·3‰,ŽÛˆ€‚ ®¬_RÈŸ…o~õÊ÷Ûÿ Æ&G-à·Á¶ýÃ/ç^Äñl|–˜²)¹J$pY÷¯1½6}K„âØ·oüPÕ-™hÝ3|´k² u !tê"†KŒ²oSð¬T-žJ>Ï`GßÁÀ¿0*'>~gϫƂ¬±Nz$Øö’”} ǃüêÕZ ;SBKçy¡m/WnߨõõÔļ14zø““]C4#Áº.@µÓ)“ÌlÔ=Û«ÛDñ vÏ"~SžbTÁ¬H´æô™ûw[LàH®©›9wb\gŸ±›ÁƒB€çÕIw(œ–Ë,E›à+š…M¾ès¼w€Ðý&ÐÚ`6òÀ]£à»¤v±¤¨T"ÒYöŒKQÂñç±Õ[ÿ–(o6L¤Ñl*¥4MAà;(r˜–äâ_!Z"Éú’@WMte뤶FpVC<¦ ƒeP !„fJ•Àén5šIÅŸe¥hâ…±¸M¼=Á½¿Kx7š!òH·[47v“6 TjU¤ˆªºÅìýòCžiȱV˜$²V‰>¡ç†&±d»%Ž×±4‰éêlcymàŽâ³ w¯ŠždÓ]¥ZºN&ãc KSغdr+¤Ûÿ@¯/r(×Ï™_.(àKãæ¹…{ççÏ zõZßsû(».qûi¢º‰m[XšÀUÒ?Á?%öïåf~¥•«3ãs™¡¾û{~îO¿·ñ„àq†Ç‡^—B~ eÔÉ(ó¨®w€³3ãsßìäÿ¸î™rÅîF IEND®B`‚simpleid/www/html/lock.png0000644000175000017500000000135511710103700015356 0ustar danieldaniel‰PNG  IHDRóÿagAMA¯È7ŠétEXtSoftwareAdobe ImageReadyqÉe<IDAT8ËmRAkA}›¤I›µ54JM›hAAÄ[=‚=ˆâA½ySP„@Ní±sì¯ð"zöˆ©ZÐF›–4(”“&¦Ivvf}³kÚµ:ð13ß|ß›÷ÞŒaÛ6¼ciiiD)5'¥œaœd€ñ“±bYÖb.—ûå­7¼…Bá ›—“Éäd,ƒÏç÷èõz¨×ëØâ нùùùµØ<ÂÃét:cš&jµ:޾@‰D©+‹Ì]^XXèê½o€Ää³ñññŒåry³Ýn§¸êÐëR©ôC“]†R²ƒ¾À`ÁäL$A¥R›îd³ÙªGj5ŸÏ߬V«ÅT*åÔþ`Lkæmz½…#Cç4;]C¶cy°ý摽R™ÆÎ^ØÑ|÷Ò*ü¶€--Ø–BH¼X»ê˜šnàö™UL?ù`¸ òàþ ´Äð‡9ß”A~Ãú H«ç³æ…Ó²ñòí¡}“.´v_!…aŒ°pÇ™VÀþdëÌîw(káÉ,l³ï E(}“‰æú{ê<†øÅk¨½^dÿiL\ŸEóë:ˆ¦N°„-L/€pdؤŸ¾_p”î(ȾħÝ0&`"žžD¯bí¾Ãjàü›îjT­µñy,ÞñÄ‚ê)ô»¤j“Yé šåmW®RNÏ!½Ñ¨”?Ÿ‚?rŠ&¦>Å”`CkÇÓI[C.Ê=`:¨ÊÒ¬ ÓÈ@y ÐD·Q‡è´ˆÑnåÊöh ¡³>ç‡ ¹OèãK(J3»ˆvÛTØ'Qéú¥?à“l.Ϲ^8Gü ë`æs?–”îZqür²²Í‡oÁEIEND®B`‚simpleid/www/html/block.xtpl0000644000175000017500000000062511710103700015722 0ustar danieldaniel

{title}

{content}
simpleid/www/discovery.inc0000644000175000017500000006133211710103700015457 0ustar danieldaniel 'application/xrds+xml')); if (isset($response['http-error'])) return NULL; if (($response['content-type'] == 'application/xrds+xml') || ($check == FALSE)) { return $response['data']; } elseif (isset($response['headers']['x-xrds-location'])) { return discovery_get_xrds($response['headers']['x-xrds-location'], false, $retries - 1); } else { $location = _discovery_meta_httpequiv('X-XRDS-Location', $response['data']); if ($location) { return discovery_get_xrds($location, false, $retries - 1); } return NULL; } } /** * Normalises an identifier for discovery. * * If the identifier begins with xri://, acct: or mailto:, this is stripped out. If the identifier * does not begin with a valid URI scheme, http:// is assumed and added to the * identifier. * * @param string $identifier the identifier to normalise * @return string the normalised identifier */ function discovery_normalize($identifier) { $normalized = $identifier; if (discovery_is_xri($identifier)) { if (stristr($identifier, 'xri://') !== false) $normalized = substr($identifier, 6); } elseif (discovery_is_email($identifier)) { if (stristr($identifier, 'acct:') !== false) $normalized = substr($identifier, 5); if (stristr($identifier, 'mailto:') !== false) $normalized = substr($identifier, 7); } else { if (stristr($identifier, '://') === false) $normalized = 'http://'. $identifier; if (substr_count($normalized, '/') < 3) $normalized .= '/'; } return $normalized; } /** * Obtains a URL for an identifier. If the identifier is a XRI, the XRI resolution * service is used to convert the identifier to a URL. * * @param string $identifier the identifier * @return string the URL */ function discovery_get_url($identifier) { if (discovery_is_xri($identifier)) { return 'http://xri.net/' . $identifier; } elseif (discovery_is_email($identifier)) { //list($user, $host) = explode('@', $identifier, 2); //$host_meta = 'http://' . $host . '/.well-known/host-meta'; } else { return $identifier; } } /** * Determines whether an identifier is an XRI. * * XRI identifiers either start with xri:// or with @, =, +, $ or !. * * @param string $identifier the parameter to test * @return bool true if the identifier is an XRI */ function discovery_is_xri($identifier) { $firstchar = substr($identifier, 0, 1); if ($firstchar == "@" || $firstchar == "=" || $firstchar == "+" || $firstchar == "\$" || $firstchar == "!") return true; if (stristr($identifier, 'xri://') !== FALSE) return true; return false; } /** * Determines whether an identifier is an e-mail address. * * An identifier is an e-mail address if it: * * - has a single @ character * - does not have a slash character * * @param string $identifier the parameter to test * @return bool true if the identifier is an e-mail address */ function discovery_is_email($identifier) { // If it begins with acct: or mailto:, strip it out if (stristr($identifier, 'acct:') !== false) $identifier = substr($identifier, 5); if (stristr($identifier, 'mailto:') !== false) $identifier = substr($identifier, 7); // If it contains a slash, it is not an e-mail address if (strpos($identifier, "/") !== false) return false; $at = strpos($identifier, "@"); // If it does not contain a @, it is not an e-mail address if ($at === false) return false; // If it contains more than one @, it is not an e-mail if (strrpos($identifier, "@") != $at) return false; return true; } /** * Callback function to sort service and URI elements based on priorities * specified in the XRDS document. * * The XRDS specification allows multiple instances of certain elements, such * as Service and URI. The specification allows an attribute called priority * so that the document creator can specify the order the elements should be used. * * @param array $a * @param array $b * @return int */ function discovery_priority_sort($a, $b) { if (!isset($a['#priority']) && !isset($b['#priority'])) return 0; // if #priority is missing, #priority is assumed to be infinity if (!isset($a['#priority'])) return 1; if (!isset($b['#priority'])) return -1; if ($a['#priority'] == $b['#priority']) return 0; return ($a['#priority'] < $b['#priority']) ? -1 : 1; } /** * Parses an XRDS document to return services available. * * @param string $xrds the XRDS document * @return array the parsed structure * * @see XRDSParser */ function discovery_parse_xrds($xrds) { // Allow for PHP5 version of xtemplate if (version_compare(PHP_VERSION, '5.0.0') === 1) { $parser = new XRDSParser(); } else { $parser =& new XRDSParser(); } $parser->parse($xrds); $parser->free(); $services = $parser->services(); uasort($services, 'discovery_priority_sort'); return $services; } /** * Obtains the OpenID services for particular identifier by scanning for link * elements in the returned document. * * Note that this function does not use the YADIS protocol to scan for services. * To use the YADIS protocol, use {@link discovery_get_services()}. * * @param string $url the URL * @return array an array of discovered services, or an empty array if no services * are found */ function discovery_get_openid_services($url) { $services = array(); $response = http_make_request($url); $html = $response['data']; $uri = _discovery_link_rel('openid2.provider', $html); $delegate = _discovery_link_rel('openid2.local_id', $html); if ($uri) { $service = array( 'type' => 'http://specs.openid.net/auth/2.0/signon', 'uri' => $uri ); if ($delegate) $service['localid'] = $delegate; $services[] = $service; } $uri = _discovery_link_rel('openid.server', $html); $delegate = _discovery_link_rel('openid.delegate', $html); if ($uri) { $service = array( 'type' => 'http://openid.net/signon/1.0', 'uri' => $uri ); if ($delegate) $service['localid'] = $delegate; $services[] = $service; } return $services; } /** * Generates a URI from a URI template and another URI. * * The URI must be able to be parsed by PHP's parse_url function. * * @param string $template the URI template * @param string $uri the input URI * @return string the generated URI * */ function discovery_uri_template($template, $uri) { $parts = @parse_url($uri); // The {uri} template variable excludes the fragment $short_uri = array_shift(explode('#', $uri, 2)); // The {userinfo} template variable is the user and the pass $userinfo = (isset($parts['user'])) ? $parts['user'] . ((isset($parts['pass'])) ? ':' . $parts['pass'] : '') : ''; // The {authority] tempalte is the userinfo, host and port $authority = $userinfo . ((isset($parts['host'])) ? '@' . $parts['host'] . ((isset($parts['port'])) ? ':' . $parts['port'] : '') : ''); $args = array( 'uri' => $short_uri, 'scheme' => (isset($parts['scheme'])) ? $parts['scheme'] : '', 'authority' => $authority, 'path' => (isset($parts['path'])) ? $parts['path'] : '', 'query' => (isset($parts['query'])) ? $parts['query'] : '', 'fragment' => (isset($parts['fragment'])) ? $parts['fragment'] : '', 'userinfo' => $userinfo, 'host' => (isset($parts['host'])) ? $parts['host'] : '', 'port' => (isset($parts['port'])) ? $parts['port'] : '' ); // Define the % encoded versions foreach ($args as $key => $value) { $args['%' . $key] = rfc3986_urlencode($value); } return strtr($template, $args); } /** * Searches through an HTML document to obtain the value of a meta * element with a specified http-equiv attribute. * * @param string $equiv the http-equiv attribute for which to search * @param string $html the HTML document to search * @return mixed the value of the meta element, or FALSE if the element is not * found */ function _discovery_meta_httpequiv($equiv, $html) { $html = preg_replace('//', '', $html); // Strip html comments $equiv = preg_quote($equiv); preg_match('||iUs', $html, $matches); if (isset($matches[1])) { preg_match('|content=["\']([^"]+)["\']|iUs', $matches[1], $content); if (isset($content[1])) { return $content[1]; } } return FALSE; } /** * Searches through an HTML document to obtain the value of a link * element with a specified rel attribute. * * @param string $rel the rel attribute for which to search * @param string $html the HTML document to search * @return mixed the href of the link element, or FALSE if the element is not * found */ function _discovery_link_rel($rel, $html) { $html = preg_replace('//s', '', $html); // Strip html comments $rel = preg_quote($rel); preg_match('||iUs', $html, $matches); if (isset($matches[3])) { preg_match('|href=["\']([^"]+)["\']|iU', $matches[3], $href); return trim($href[1]); } return FALSE; } /** * A simple XRDS parser. * * This parser uses the classic expat functions available in PHP to parse the * XRDS Simple XML document. * * The result is an array of discovered services. * * @link http://xrds-simple.net/ */ class XRDSParser { /** * XML parser * @var resource * @access private */ var $parser; /** * Discovered services * @var array * @access private */ var $services = array(); /** * State: are we parsing a service element? * @var bool * @access private */ var $in_service = FALSE; /** * CDATA buffer * @var string * @access private */ var $_buffer; /** * Attributes buffer * @var array * @access private */ var $_attribs = array(); /** * priority attribute buffer * @var string * @access private */ var $priority = NULL; /** * Currently parsed service buffer * @var array * @access private */ var $service = array(); /** * The canonical identifier for the resource described. Used in XRD * documents only. * @var string * @access private * @since 0.8 */ var $subject = NULL; /** * Additional identifies for the resource described. Used in XRD * documents only. * @var array * @access private * @since 0.8 */ var $aliases = array(); /** * Additional properties for the resource described. Used in XRD * documents only. * @var array * @access private * @since 0.8 */ var $properties = array(); /** * Mapping between XRDS elements and XRD attributes * @var array * @access private * @since 0.8 */ var $xrds_map = array( 'rel' => 'type', 'href' => 'uri' ); /** * Creates an instance of the XRDS parser. * * This constructor also initialises the underlying XML parser. */ function XRDSParser() { $this->parser = xml_parser_create_ns(); xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING,0); xml_set_object($this->parser, $this); xml_set_element_handler($this->parser, 'element_start', 'element_end'); xml_set_character_data_handler($this->parser, 'cdata'); } /** * Frees memory associated with the underlying XML parser. * * Note that only the memory associated with the underlying XML parser is * freed. Memory associated with the class itself is not freed. * * @access public */ function free() { xml_parser_free($this->parser); } /** * Parses an XRDS document. * * Once the parsing is complete, use {@link XRDSParser::services()} to obtain * the services extracted from the document. * * @param string $xml the XML document to parse * @access public */ function parse($xml) { xml_parse($this->parser, $xml); } /** * Gets an array of discovered services. * * @return array an array of discovered services, or an empty array * @access public * @see XRDSParser::parse() */ function services() { return $this->services; } /** * Returns the canonical identifier. * * @return string the canonical identifier * @access public * @since 0.8 */ function subject() { return $this->subject; } /** * Returns additional identifiers. * * @return array the additional identifiers * @access public * @since 0.8 */ function aliases() { return $this->aliases; } /** * Returns additional properties. * * @return array the additional properties * @access public * @since 0.8 */ function properties() { return $this->properties; } /** * XML parser callback * * @access private */ function element_start(&$parser, $qualified, $attribs) { list($ns, $name) = $this->parse_namespace($qualified); // Strictly speaking, XML namespace URIs are semi-case sensitive // (i.e. the scheme and host are not case sensitive, but other elements // are). However, the XRDS-Simple specifications defines a // namespace URI for XRD (xri://$XRD*($v*2.0) rather than xri://$xrd*($v*2.0)) // with an unusual case. if ((strtolower($ns) == strtolower(XRD2_NS)) && ($name == 'Service')) { $this->in_service = TRUE; $this->service = array(); if (in_array('priority', $attribs)) { $this->service['#priority'] = $attribs['priority']; } if (in_array('id', $attribs)) { $this->service['#id'] = $attribs['id']; } } if (($ns == XRD_NS) && ($name == 'Link')) { $this->in_service = TRUE; $this->service = array(); foreach ($attribs as $name => $value) { $this->service[(in_array($name, $this->xrds_map)) ? $this->xrds_map[$name] : $name] = $value; } } if ((strtolower($ns) == strtolower(XRD2_NS)) && ($this->in_service)) { switch ($name) { case 'Type': case 'LocalID': case 'URI': if (in_array('priority', $attribs)) { $this->priority = $attribs['priority']; } else { $this->priority = NULL; } } } if (strtolower($ns) == strtolower(XRD_NS)) { $this->priority = NULL; } $this->_buffer = ''; $this->_attribs = $attribs; } /** * XML parser callback * * @access private */ function element_end(&$parser, $qualified) { list($ns, $name) = $this->parse_namespace($qualified); if (($ns == XRD_NS) && !$this->in_service) { switch ($name) { case 'Subject': $this->subject = trim($this->_buffer); break; case 'Alias': $this->aliases[] = trim($this->_buffer); break; case 'Property': $this->properties[$this->_attribs['type']] = trim($this->_buffer); break; } } if ((strtolower($ns) == strtolower(XRD2_NS)) && ($this->in_service)) { switch ($name) { case 'Service': foreach (array('type', 'localid', 'uri') as $key) { if (!isset($this->service[$key])) continue; $this->service[$key] = $this->flatten_uris($this->service[$key]); } $this->services[] = $this->service; $this->in_service = FALSE; break; case 'Type': case 'LocalID': case 'URI': $key = strtolower($name); if (!isset($this->service[$key])) { $this->service[$key] = array(); } if ($this->priority != NULL) { $this->service[$key][] = array('#uri' => trim($this->_buffer), '#priority' => $this->priority); } else { $this->service[$key][] = array('#uri' => trim($this->_buffer)); } $this->priority = NULL; break; } } if (($ns == XRD_NS) && ($this->in_service)) { switch ($name) { case 'Link': $this->services[] = $this->service; $this->in_service = FALSE; break; case 'Property': if (!isset($this->service['properties'])) $this->service['properties'] = array(); $this->service['properties'][$this->_attribs['type']] = trim($this->_buffer); case 'Title': $this->service['title'] = trim($this->_buffer); break; } } if ((strtolower($ns) == strtolower(XRD_OPENID_NS)) && ($this->in_service)) { switch ($name) { case 'Delegate': $this->service['delegate'] = trim($this->_buffer); } } $this->_attribs = array(); } /** * XML parser callback * * @access private */ function cdata(&$parser, $data) { $this->_buffer .= $data; } /** * Parses a namespace-qualified element name. * * @param string $qualified the qualified name * @return array an array with two elements - the first element contains * the namespace qualifier (or an empty string), the second element contains * the element name * @access protected */ function parse_namespace($qualified) { $pos = strrpos($qualified, ':'); if ($pos !== FALSE) return array(substr($qualified, 0, $pos), substr($qualified, $pos + 1, strlen($qualified))); return array('', $qualified); } /** * Flattens the service array. * * In an XRDS document, child elements of the service element often contains * a list of URIs, with the priority specified in the priority attribute. * * When the document is parsed in this class, the URI and the priority are first * extracted into the #uri and the #priority keys respectively. This function * takes this array, sorts the elements using the #priority keys (if $sort is * true), then collapses the array using the value associated with the #uri key. * * @param array $array the service array, with URIs and priorities * @param bool $sort whether to sort the service array using the #priority * keys * @return array the services array with URIs sorted by priority * @access protected */ function flatten_uris($array, $sort = TRUE) { $result = array(); if ($sort) uasort($array, 'discovery_priority_sort'); for ($i = 0; $i < count($array); $i++) { $result[] = $array[$i]['#uri']; } return $result; } } if (!function_exists('rfc3986_urlencode')) { /** * Encodes a URL using RFC 3986. * * PHP's rawurlencode function encodes a URL using RFC 1738. RFC 1738 has been * updated by RFC 3986, which change the list of characters which needs to be * encoded. * * Strictly correct encoding is required for various purposes, such as OAuth * signature base strings. * * @param string $s the URL to encode * @return string the encoded URL */ function rfc3986_urlencode($s) { return str_replace('%7E', '~', rawurlencode($s)); } } ?> simpleid/www/lib/0000755000175000017500000000000011746513204013533 5ustar danieldanielsimpleid/www/lib/xtemplate-php4.class.php0000644000175000017500000007670411710103700020225 0ustar danieldaniel'; /** * Template block start word * * @access public * @var string */ var $block_start_word = 'BEGIN:'; /** * Template block end word * * The last 3 properties and this make the delimiters look like: * @example * if you use the default syntax. * * @access public * @var string */ var $block_end_word = 'END:'; /** * Template tag start delimiter * * This makes the delimiters look like: * @example {tagname} * if you use the default syntax. * * @access public * @var string */ var $tag_start_delim = '{'; /** * Template tag end delimiter * * This makes the delimiters look like: * @example {tagname} * if you use the default syntax. * * @access public * @var string */ var $tag_end_delim = '}'; /* this makes the delimiters look like: {tagname} if you use my syntax. */ /** * Regular expression element for comments within tags and blocks * * @example {tagname#My Comment} * @example {tagname #My Comment} * @example * @example * * @access public * @var string */ var $comment_preg = '( ?#.*?)?'; /** * Default main template block name * * @access public * @var string */ var $mainblock = 'main'; /** * Script output type * * @access public * @var string */ var $output_type = 'HTML'; /** * Debug mode * * @access public * @var boolean */ var $debug = false; /** * Null string for unassigned vars * * @access protected * @var array */ var $_null_string = array('' => ''); /** * Null string for unassigned blocks * * @access protected * @var array */ var $_null_block = array('' => ''); /** * Errors * * @access protected * @var string */ var $_error = ''; /** * Auto-reset sub blocks * * @access protected * @var boolean */ var $_autoreset = true; /** * Set to FALSE to generate errors if a non-existant blocks is referenced * * @author NW * @since 2002/10/17 * @access protected * @var boolean */ var $_ignore_missing_blocks = true; /** * Constructor - Instantiate the object * * @param string $file Template file to work on * @param string $tpldir Location of template files (useful for keeping files outside web server root) * @param array $files Filenames lookup * @param string $mainblock Name of main block in the template * @param boolean $autosetup If true, run setup() as part of constuctor * @return XTemplate */ function XTemplate ($file, $tpldir = '', $files = null, $mainblock = 'main', $autosetup = true) { $this->restart($file, $tpldir, $files, $mainblock, $autosetup, $this->tag_start_delim, $this->tag_end_delim); } /***************************************************************************/ /***[ public stuff ]********************************************************/ /***************************************************************************/ /** * Restart the class - allows one instantiation with several files processed by restarting * e.g. $xtpl = new XTemplate('file1.xtpl'); * $xtpl->parse('main'); * $xtpl->out('main'); * $xtpl->restart('file2.xtpl'); * $xtpl->parse('main'); * $xtpl->out('main'); * (Added in response to sf:641407 feature request) * * @param string $file Template file to work on * @param string $tpldir Location of template files * @param array $files Filenames lookup * @param string $mainblock Name of main block in the template * @param boolean $autosetup If true, run setup() as part of restarting * @param string $tag_start { * @param string $tag_end } */ function restart ($file, $tpldir = '', $files = null, $mainblock = 'main', $autosetup = true, $tag_start = '{', $tag_end = '}') { $this->filename = $file; // From SF Feature request 1202027 // Kenneth Kalmer $this->tpldir = $tpldir; if (defined('XTPL_DIR') && empty($this->tpldir)) { $this->tpldir = XTPL_DIR; } if (is_array($files)) { $this->files = $files; } $this->mainblock = $mainblock; $this->tag_start_delim = $tag_start; $this->tag_end_delim = $tag_end; // Start with fresh file contents $this->filecontents = ''; // Reset the template arrays $this->blocks = array(); $this->parsed_blocks = array(); $this->preparsed_blocks = array(); $this->block_parse_order = array(); $this->sub_blocks = array(); $this->vars = array(); $this->filevars = array(); $this->filevar_parent = array(); $this->filecache = array(); if ($autosetup) { $this->setup(); } } /** * setup - the elements that were previously in the constructor * * @access public * @param boolean $add_outer If true is passed when called, it adds an outer main block to the file */ function setup ($add_outer = false) { $this->tag_start_delim = preg_quote($this->tag_start_delim); $this->tag_end_delim = preg_quote($this->tag_end_delim); // Setup the file delimiters // regexp for file includes $this->file_delim = "/" . $this->tag_start_delim . "FILE\s*\"([^\"]+)\"" . $this->comment_preg . $this->tag_end_delim . "/m"; // regexp for file includes $this->filevar_delim = "/" . $this->tag_start_delim . "FILE\s*" . $this->tag_start_delim . "([A-Za-z0-9\._]+?)" . $this->comment_preg . $this->tag_end_delim . $this->comment_preg . $this->tag_end_delim . "/m"; // regexp for file includes w/ newlines $this->filevar_delim_nl = "/^\s*" . $this->tag_start_delim . "FILE\s*" . $this->tag_start_delim . "([A-Za-z0-9\._]+?)" . $this->comment_preg . $this->tag_end_delim . $this->comment_preg . $this->tag_end_delim . "\s*\n/m"; if (empty($this->filecontents)) { // read in template file $this->filecontents = $this->_r_getfile($this->filename); } if ($add_outer) { $this->_add_outer_block(); } // preprocess some stuff $this->blocks = $this->_maketree($this->filecontents, ''); $this->filevar_parent = $this->_store_filevar_parents($this->blocks); $this->scan_globals(); } /** * assign a variable * * @example Simplest case: * @example $xtpl->assign('name', 'value'); * @example {name} in template * * @example Array assign: * @example $xtpl->assign(array('name' => 'value', 'name2' => 'value2')); * @example {name} {name2} in template * * @example Value as array assign: * @example $xtpl->assign('name', array('key' => 'value', 'key2' => 'value2')); * @example {name.key} {name.key2} in template * * @example Reset array: * @example $xtpl->assign('name', array('key' => 'value', 'key2' => 'value2')); * @example // Other code then: * @example $xtpl->assign('name', array('key3' => 'value3'), false); * @example {name.key} {name.key2} {name.key3} in template * * @access public * @param string $name Variable to assign $val to * @param string / array $val Value to assign to $name * @param boolean $reset_array Reset the variable array if $val is an array */ function assign ($name, $val = '', $reset_array = true) { if (is_array($name)) { foreach ($name as $k => $v) { $this->vars[$k] = $v; } } elseif (is_array($val)) { // Clear the existing values if ($reset_array) { $this->vars[$name] = array(); } foreach ($val as $k => $v) { $this->vars[$name][$k] = $v; } } else { $this->vars[$name] = $val; } } /** * assign a file variable * * @access public * @param string $name Variable to assign $val to * @param string / array $val Values to assign to $name */ function assign_file ($name, $val = '') { if (is_array($name)) { foreach ($name as $k => $v) { $this->_assign_file_sub($k, $v); } } else { $this->_assign_file_sub($name, $val); } } /** * parse a block * * @access public * @param string $bname Block name to parse */ function parse ($bname) { if (isset($this->preparsed_blocks[$bname])) { $copy = $this->preparsed_blocks[$bname]; } elseif (isset($this->blocks[$bname])) { $copy = $this->blocks[$bname]; } elseif ($this->_ignore_missing_blocks) { // ------------------------------------------------------ // NW : 17 Oct 2002. Added default of ignore_missing_blocks // to allow for generalised processing where some // blocks may be removed from the HTML without the // processing code needing to be altered. // ------------------------------------------------------ // JRC: 3/1/2003 added set error to ignore missing functionality $this->_set_error("parse: blockname [$bname] does not exist"); return; } else { $this->_set_error("parse: blockname [$bname] does not exist"); } /* from there we should have no more {FILE } directives */ if (!isset($copy)) { die('Block: ' . $bname); } $copy = preg_replace($this->filevar_delim_nl, '', $copy); $var_array = array(); /* find & replace variables+blocks */ preg_match_all("|" . $this->tag_start_delim . "([A-Za-z0-9\._]+?" . $this->comment_preg . ")" . $this->tag_end_delim. "|", $copy, $var_array); $var_array = $var_array[1]; foreach ($var_array as $k => $v) { // Are there any comments in the tags {tag#a comment for documenting the template} $any_comments = explode('#', $v); $v = rtrim($any_comments[0]); if (sizeof($any_comments) > 1) { $comments = $any_comments[1]; } else { $comments = ''; } $sub = explode('.', $v); if ($sub[0] == '_BLOCK_') { unset($sub[0]); $bname2 = implode('.', $sub); // trinary operator eliminates assign error in E_ALL reporting $var = isset($this->parsed_blocks[$bname2]) ? $this->parsed_blocks[$bname2] : null; $nul = (!isset($this->_null_block[$bname2])) ? $this->_null_block[''] : $this->_null_block[$bname2]; if ($var === '') { if ($nul == '') { // ----------------------------------------------------------- // Removed requirement for blocks to be at the start of string // ----------------------------------------------------------- // $copy=preg_replace("/^\s*\{".$v."\}\s*\n*/m","",$copy); // Now blocks don't need to be at the beginning of a line, //$copy=preg_replace("/\s*" . $this->tag_start_delim . $v . $this->tag_end_delim . "\s*\n*/m","",$copy); $copy = preg_replace("|" . $this->tag_start_delim . $v . $this->tag_end_delim . "|m", '', $copy); } else { $copy = preg_replace("|" . $this->tag_start_delim . $v . $this->tag_end_delim . "|m", "$nul", $copy); } } else { //$var = trim($var); switch (true) { case preg_match('/^\n/', $var) && preg_match('/\n$/', $var): $var = substr($var, 1, -1); break; case preg_match('/^\n/', $var): $var = substr($var, 1); break; case preg_match('/\n$/', $var): $var = substr($var, 0, -1); break; } // SF Bug no. 810773 - thanks anonymous $var = str_replace('\\', '\\\\', $var); // Ensure dollars in strings are not evaluated reported by SadGeezer 31/3/04 $var = str_replace('$', '\\$', $var); // Replaced str_replaces with preg_quote //$var = preg_quote($var); $var = str_replace('\\|', '|', $var); $copy = preg_replace("|" . $this->tag_start_delim . $v . $this->tag_end_delim . "|m", "$var", $copy); if (preg_match('/^\n/', $copy) && preg_match('/\n$/', $copy)) { $copy = substr($copy, 1, -1); } } } else { $var = $this->vars; foreach ($sub as $v1) { // NW 4 Oct 2002 - Added isset and is_array check to avoid NOTICE messages // JC 17 Oct 2002 - Changed EMPTY to stlen=0 // if (empty($var[$v1])) { // this line would think that zeros(0) were empty - which is not true if (!isset($var[$v1]) || (!is_array($var[$v1]) && strlen($var[$v1]) == 0)) { // Check for constant, when variable not assigned if (defined($v1)) { $var[$v1] = constant($v1); } else { $var[$v1] = null; } } $var = $var[$v1]; } $nul = (!isset($this->_null_string[$v])) ? ($this->_null_string[""]) : ($this->_null_string[$v]); $var = (!isset($var)) ? $nul : $var; if ($var === '') { // ----------------------------------------------------------- // Removed requriement for blocks to be at the start of string // ----------------------------------------------------------- // $copy=preg_replace("|^\s*\{".$v." ?#?".$comments."\}\s*\n|m","",$copy); $copy = preg_replace("|" . $this->tag_start_delim . $v . "( ?#" . $comments . ")?" . $this->tag_end_delim . "|m", '', $copy); } $var = trim($var); // SF Bug no. 810773 - thanks anonymous $var = str_replace('\\', '\\\\', $var); // Ensure dollars in strings are not evaluated reported by SadGeezer 31/3/04 $var = str_replace('$', '\\$', $var); // Replace str_replaces with preg_quote //$var = preg_quote($var); $var = str_replace('\\|', '|', $var); $copy = preg_replace("|" . $this->tag_start_delim . $v . "( ?#" . $comments . ")?" . $this->tag_end_delim . "|m", "$var", $copy); if (preg_match('/^\n/', $copy) && preg_match('/\n$/', $copy)) { $copy = substr($copy, 1); } } } if (isset($this->parsed_blocks[$bname])) { $this->parsed_blocks[$bname] .= $copy; } else { $this->parsed_blocks[$bname] = $copy; } /* reset sub-blocks */ if ($this->_autoreset && (!empty($this->sub_blocks[$bname]))) { reset($this->sub_blocks[$bname]); foreach ($this->sub_blocks[$bname] as $k => $v) { $this->reset($v); } } } /** * returns the parsed text for a block, including all sub-blocks. * * @access public * @param string $bname Block name to parse */ function rparse ($bname) { if (!empty($this->sub_blocks[$bname])) { reset($this->sub_blocks[$bname]); foreach ($this->sub_blocks[$bname] as $k => $v) { if (!empty($v)) { $this->rparse($v); } } } $this->parse($bname); } /** * inserts a loop ( call assign & parse ) * * @access public * @param string $bname Block name to assign * @param string $var Variable to assign values to * @param string / array $value Value to assign to $var */ function insert_loop ($bname, $var, $value = '') { $this->assign($var, $value); $this->parse($bname); } /** * parses a block for every set of data in the values array * * @access public * @param string $bname Block name to loop * @param string $var Variable to assign values to * @param array $values Values to assign to $var */ function array_loop ($bname, $var, &$values) { if (is_array($values)) { foreach($values as $v) { $this->insert_loop($bname, $var, $v); } } } /** * returns the parsed text for a block * * @access public * @param string $bname Block name to return * @return string */ function text ($bname = '') { $text = ''; if ($this->debug && $this->output_type == 'HTML') { // JC 20/11/02 echo the template filename if in development as // html comment $text .= '\n"; } $bname = !empty($bname) ? $bname : $this->mainblock; $text .= isset($this->parsed_blocks[$bname]) ? $this->parsed_blocks[$bname] : $this->get_error(); return $text; } /** * prints the parsed text * * @access public * @param string $bname Block name to echo out */ function out ($bname) { $out = $this->text($bname); // $length=strlen($out); //header("Content-Length: ".$length); // TODO: Comment this back in later echo $out; } /** * prints the parsed text to a specified file * * @access public * @param string $bname Block name to write out * @param string $fname File name to write to */ function out_file ($bname, $fname) { if (!empty($bname) && !empty($fname) && is_writeable($fname)) { $fp = fopen($fname, 'w'); fwrite($fp, $this->text($bname)); fclose($fp); } } /** * resets the parsed text * * @access public * @param string $bname Block to reset */ function reset ($bname) { $this->parsed_blocks[$bname] = ''; } /** * returns true if block was parsed, false if not * * @access public * @param string $bname Block name to test * @return boolean */ function parsed ($bname) { return (!empty($this->parsed_blocks[$bname])); } /** * sets the string to replace in case the var was not assigned * * @access public * @param string $str Display string for null block * @param string $varname Variable name to apply $str to */ function set_null_string($str, $varname = '') { $this->_null_string[$varname] = $str; } /** * Backwards compatibility only * * @param string $str * @param string $varname * @deprecated Change to set_null_string to keep in with rest of naming convention */ function SetNullString ($str, $varname = '') { $this->set_null_string($str, $varname); } /** * sets the string to replace in case the block was not parsed * * @access public * @param string $str Display string for null block * @param string $bname Block name to apply $str to */ function set_null_block ($str, $bname = '') { $this->_null_block[$bname] = $str; } /** * Backwards compatibility only * * @param string $str * @param string $bname * @deprecated Change to set_null_block to keep in with rest of naming convention */ function SetNullBlock ($str, $bname = '') { $this->set_null_block($str, $bname); } /** * sets AUTORESET to 1. (default is 1) * if set to 1, parse() automatically resets the parsed blocks' sub blocks * (for multiple level blocks) * * @access public */ function set_autoreset () { $this->_autoreset = true; } /** * sets AUTORESET to 0. (default is 1) * if set to 1, parse() automatically resets the parsed blocks' sub blocks * (for multiple level blocks) * * @access public */ function clear_autoreset () { $this->_autoreset = false; } /** * scans global variables and assigns to PHP array * * @access public */ function scan_globals () { reset($GLOBALS); foreach ($GLOBALS as $k => $v) { $GLOB[$k] = $v; } /** * Access global variables as: * @example {PHP._SERVER.HTTP_HOST} * in your template! */ $this->assign('PHP', $GLOB); } /** * gets error condition / string * * @access public * @return boolean / string */ function get_error () { // JRC: 3/1/2003 Added ouptut wrapper and detection of output type for error message output $retval = false; if ($this->_error != '') { switch ($this->output_type) { case 'HTML': case 'html': $retval = '[XTemplate]
    ' . nl2br(str_replace('* ', '
  • ', str_replace(" *\n", "
  • \n", $this->_error))) . '
'; break; default: $retval = '[XTemplate] ' . str_replace(' *\n', "\n", $this->_error); break; } } return $retval; } /***************************************************************************/ /***[ private stuff ]*******************************************************/ /***************************************************************************/ /** * generates the array containing to-be-parsed stuff: * $blocks["main"],$blocks["main.table"],$blocks["main.table.row"], etc. * also builds the reverse parse order. * * @access public - aiming for private * @param string $con content to be processed * @param string $parentblock name of the parent block in the block hierarchy */ function _maketree ($con, $parentblock='') { $blocks = array(); $con2 = explode($this->block_start_delim, $con); if (!empty($parentblock)) { $block_names = explode('.', $parentblock); $level = sizeof($block_names); } else { $block_names = array(); $level = 0; } // JRC 06/04/2005 Added block comments (on BEGIN or END) //$patt = "($this->block_start_word|$this->block_end_word)\s*(\w+)\s*$this->block_end_delim(.*)"; $patt = "(" . $this->block_start_word . "|" . $this->block_end_word . ")\s*(\w+)" . $this->comment_preg . "\s*" . $this->block_end_delim . "(.*)"; foreach($con2 as $k => $v) { $res = array(); if (preg_match_all("/$patt/ims", $v, $res, PREG_SET_ORDER)) { // $res[0][1] = BEGIN or END // $res[0][2] = block name // $res[0][3] = comment // $res[0][4] = kinda content $block_word = $res[0][1]; $block_name = $res[0][2]; $comment = $res[0][3]; $content = $res[0][4]; if (strtoupper($block_word) == $this->block_start_word) { $parent_name = implode('.', $block_names); // add one level - array("main","table","row") $block_names[++$level] = $block_name; // make block name (main.table.row) $cur_block_name=implode('.', $block_names); // build block parsing order (reverse) $this->block_parse_order[] = $cur_block_name; //add contents. trinary operator eliminates assign error in E_ALL reporting $blocks[$cur_block_name] = isset($blocks[$cur_block_name]) ? $blocks[$cur_block_name] . $content : $content; // add {_BLOCK_.blockname} string to parent block $blocks[$parent_name] .= str_replace('\\', '', $this->tag_start_delim) . '_BLOCK_.' . $cur_block_name . str_replace('\\', '', $this->tag_end_delim); // store sub block names for autoresetting and recursive parsing $this->sub_blocks[$parent_name][] = $cur_block_name; // store sub block names for autoresetting $this->sub_blocks[$cur_block_name][] = ''; } else if (strtoupper($block_word) == $this->block_end_word) { unset($block_names[$level--]); $parent_name = implode('.', $block_names); // add rest of block to parent block $blocks[$parent_name] .= $content; } } else { // no block delimiters found // Saves doing multiple implodes - less overhead $tmp = implode('.', $block_names); if ($k) { $blocks[$tmp] .= $this->block_start_delim; } // trinary operator eliminates assign error in E_ALL reporting $blocks[$tmp] = isset($blocks[$tmp]) ? $blocks[$tmp] . $v : $v; } } return $blocks; } /** * Sub processing for assign_file method * * @access private * @param string $name * @param string $val */ function _assign_file_sub ($name, $val) { if (isset($this->filevar_parent[$name])) { if ($val != '') { $val = $this->_r_getfile($val); foreach($this->filevar_parent[$name] as $parent) { if (isset($this->preparsed_blocks[$parent]) && !isset($this->filevars[$name])) { $copy = $this->preparsed_blocks[$parent]; } elseif (isset($this->blocks[$parent])) { $copy = $this->blocks[$parent]; } $res = array(); preg_match_all($this->filevar_delim, $copy, $res, PREG_SET_ORDER); if (is_array($res) && isset($res[0])) { // Changed as per solution in SF bug ID #1261828 foreach ($res as $v) { // Changed as per solution in SF bug ID #1261828 if ($v[1] == $name) { // Changed as per solution in SF bug ID #1261828 $copy = preg_replace("/" . preg_quote($v[0]) . "/", "$val", $copy); $this->preparsed_blocks = array_merge($this->preparsed_blocks, $this->_maketree($copy, $parent)); $this->filevar_parent = array_merge($this->filevar_parent, $this->_store_filevar_parents($this->preparsed_blocks)); } } } } } } $this->filevars[$name] = $val; } /** * store container block's name for file variables * * @access public - aiming for private * @param array $blocks * @return array */ function _store_filevar_parents ($blocks){ $parents = array(); foreach ($blocks as $bname => $con) { $res = array(); preg_match_all($this->filevar_delim, $con, $res); foreach ($res[1] as $k => $v) { $parents[$v][] = $bname; } } return $parents; } /** * Set the error string * * @access private * @param string $str */ function _set_error ($str) { // JRC: 3/1/2003 Made to append the error messages $this->_error .= '* ' . $str . " *\n"; // JRC: 3/1/2003 Removed trigger error, use this externally if you want it eg. trigger_error($xtpl->get_error()) //trigger_error($this->get_error()); } /** * returns the contents of a file * * @access protected * @param string $file * @return string */ function _getfile ($file) { if (!isset($file)) { // JC 19/12/02 added $file to error message $this->_set_error('!isset file name!' . $file); return ''; } // check if filename is mapped to other filename if (isset($this->files)) { if (isset($this->files[$file])) { $file = $this->files[$file]; } } // prepend template dir if (!empty($this->tpldir)) { /** * Support hierarchy of file locations to search * * @example Supply array of filepaths when instantiating * First path supplied that has the named file is prioritised * $xtpl = new XTemplate('myfile.xtpl', array('.','/mypath', '/mypath2')); * @since 29/05/2007 */ if (is_array($this->tpldir)) { foreach ($this->tpldir as $dir) { if (is_readable($dir . DIRECTORY_SEPARATOR . $file)) { $file = $dir . DIRECTORY_SEPARATOR . $file; break; } } } else { $file = $this->tpldir. DIRECTORY_SEPARATOR . $file; } } $file_text = ''; if (isset($this->filecache[$file])) { $file_text .= $this->filecache[$file]; if ($this->debug) { $file_text = '' . "\n" . $file_text; } } else { if (is_file($file) && is_readable($file)) { if (filesize($file)) { if (!($fh = fopen($file, 'r'))) { $this->_set_error('Cannot open file: ' . realpath($file)); return ''; } $file_text .= fread($fh,filesize($file)); fclose($fh); } if ($this->debug) { $file_text = '' . "\n" . $file_text; } } elseif (str_replace('.', '', phpversion()) >= '430' && $file_text = @file_get_contents($file, true)) { // Enable use of include path by using file_get_contents // Implemented at suggestion of SF Feature Request ID #1529478 michaelgroh if ($file_text === false) { $this->_set_error("[" . realpath($file) . "] ($file) does not exist"); $file_text = "__XTemplate fatal error: file [$file] does not exist in the include path__"; } elseif ($this->debug) { $file_text = '' . "\n" . $file_text; } } elseif (!is_file($file)) { // NW 17 Oct 2002 : Added realpath around the file name to identify where the code is searching. $this->_set_error("[" . realpath($file) . "] ($file) does not exist"); $file_text .= "__XTemplate fatal error: file [$file] does not exist__"; } elseif (!is_readable($file)) { $this->_set_error("[" . realpath($file) . "] ($file) is not readable"); $file_text .= "__XTemplate fatal error: file [$file] is not readable__"; } $this->filecache[$file] = $file_text; } return $file_text; } /** * recursively gets the content of a file with {FILE "filename.tpl"} directives * * @access public - aiming for private * @param string $file * @return string */ function _r_getfile ($file) { $text = $this->_getfile($file); $res = array(); while (preg_match($this->file_delim,$text,$res)) { $text2 = $this->_getfile($res[1]); $text = preg_replace("'".preg_quote($res[0])."'",$text2,$text); } return $text; } /** * add an outer block delimiter set useful for rtfs etc - keeps them editable in word * * @access private */ function _add_outer_block () { $before = $this->block_start_delim . $this->block_start_word . ' ' . $this->mainblock . ' ' . $this->block_end_delim; $after = $this->block_start_delim . $this->block_end_word . ' ' . $this->mainblock . ' ' . $this->block_end_delim; $this->filecontents = $before . "\n" . $this->filecontents . "\n" . $after; } /** * Debug function - var_dump wrapped in '
' tags
     *
     * @access private
     * @param multiple var_dumps all the supplied arguments
     */
	function _pre_var_dump ($args) {

		if ($this->debug) {
			echo '
';
			var_dump(func_get_args());
			echo '
'; } } } /* end of XTemplate class. */ ?>simpleid/www/lib/xtemplate.class.php0000644000175000017500000010064211710103700017341 0ustar danieldaniel'; /** * Template block start word * * @access public * @var string */ public $block_start_word = 'BEGIN:'; /** * Template block end word * * The last 3 properties and this make the delimiters look like: * @example * if you use the default syntax. * * @access public * @var string */ public $block_end_word = 'END:'; /** * Template tag start delimiter * * This makes the delimiters look like: * @example {tagname} * if you use the default syntax. * * @access public * @var string */ public $tag_start_delim = '{'; /** * Template tag end delimiter * * This makes the delimiters look like: * @example {tagname} * if you use the default syntax. * * @access public * @var string */ public $tag_end_delim = '}'; /* this makes the delimiters look like: {tagname} if you use my syntax. */ /** * Regular expression element for comments within tags and blocks * * @example {tagname#My Comment} * @example {tagname #My Comment} * @example * @example * * @access public * @var string */ public $comment_preg = '( ?#.*?)?'; /** * Default main template block name * * @access public * @var string */ public $mainblock = 'main'; /** * Script output type * * @access public * @var string */ public $output_type = 'HTML'; /** * Debug mode * * @access public * @var boolean */ public $debug = false; /** * Null string for unassigned vars * * @access protected * @var array */ protected $_null_string = array('' => ''); /** * Null string for unassigned blocks * * @access protected * @var array */ protected $_null_block = array('' => ''); /** * Errors * * @access protected * @var string */ protected $_error = ''; /** * Auto-reset sub blocks * * @access protected * @var boolean */ protected $_autoreset = true; /** * Set to FALSE to generate errors if a non-existant blocks is referenced * * @author NW * @since 2002/10/17 * @access protected * @var boolean */ protected $_ignore_missing_blocks = true; /** * PHP 5 Constructor - Instantiate the object * * @param string $file Template file to work on * @param string/array $tpldir Location of template files (useful for keeping files outside web server root) * @param array $files Filenames lookup * @param string $mainblock Name of main block in the template * @param boolean $autosetup If true, run setup() as part of constuctor * @return XTemplate */ public function __construct($file, $tpldir = '', $files = null, $mainblock = 'main', $autosetup = true) { $this->restart($file, $tpldir, $files, $mainblock, $autosetup, $this->tag_start_delim, $this->tag_end_delim); } /* * PHP 4 Constructor - Instantiate the object * * @deprecated Use PHP 5 constructor instead * @param string $file Template file to work on * @param string/array $tpldir Location of template files (useful for keeping files outside web server root) * @param array $files Filenames lookup * @param string $mainblock Name of main block in the template * @param boolean $autosetup If true, run setup() as part of constuctor * @return XTemplate * public function XTemplate ($file, $tpldir = '', $files = null, $mainblock = 'main', $autosetup = true) { assert('Deprecated - use PHP 5 constructor'); }*/ /***************************************************************************/ /***[ public stuff ]********************************************************/ /***************************************************************************/ /** * Restart the class - allows one instantiation with several files processed by restarting * e.g. $xtpl = new XTemplate('file1.xtpl'); * $xtpl->parse('main'); * $xtpl->out('main'); * $xtpl->restart('file2.xtpl'); * $xtpl->parse('main'); * $xtpl->out('main'); * (Added in response to sf:641407 feature request) * * @param string $file Template file to work on * @param string/array $tpldir Location of template files * @param array $files Filenames lookup * @param string $mainblock Name of main block in the template * @param boolean $autosetup If true, run setup() as part of restarting * @param string $tag_start { * @param string $tag_end } */ public function restart ($file, $tpldir = '', $files = null, $mainblock = 'main', $autosetup = true, $tag_start = '{', $tag_end = '}') { $this->filename = $file; // From SF Feature request 1202027 // Kenneth Kalmer $this->tpldir = $tpldir; if (defined('XTPL_DIR') && empty($this->tpldir)) { $this->tpldir = XTPL_DIR; } if (is_array($files)) { $this->files = $files; } $this->mainblock = $mainblock; $this->tag_start_delim = $tag_start; $this->tag_end_delim = $tag_end; // Start with fresh file contents $this->filecontents = ''; // Reset the template arrays $this->blocks = array(); $this->parsed_blocks = array(); $this->preparsed_blocks = array(); $this->block_parse_order = array(); $this->sub_blocks = array(); $this->vars = array(); $this->filevars = array(); $this->filevar_parent = array(); $this->filecache = array(); if ($autosetup) { $this->setup(); } } /** * setup - the elements that were previously in the constructor * * @access public * @param boolean $add_outer If true is passed when called, it adds an outer main block to the file */ public function setup ($add_outer = false) { $this->tag_start_delim = preg_quote($this->tag_start_delim); $this->tag_end_delim = preg_quote($this->tag_end_delim); // Setup the file delimiters // regexp for file includes $this->file_delim = "/" . $this->tag_start_delim . "FILE\s*\"([^\"]+)\"" . $this->comment_preg . $this->tag_end_delim . "/m"; // regexp for file includes $this->filevar_delim = "/" . $this->tag_start_delim . "FILE\s*" . $this->tag_start_delim . "([A-Za-z0-9\._]+?)" . $this->comment_preg . $this->tag_end_delim . $this->comment_preg . $this->tag_end_delim . "/m"; // regexp for file includes w/ newlines $this->filevar_delim_nl = "/^\s*" . $this->tag_start_delim . "FILE\s*" . $this->tag_start_delim . "([A-Za-z0-9\._]+?)" . $this->comment_preg . $this->tag_end_delim . $this->comment_preg . $this->tag_end_delim . "\s*\n/m"; if (empty($this->filecontents)) { // read in template file $this->filecontents = $this->_r_getfile($this->filename); } if ($add_outer) { $this->_add_outer_block(); } // preprocess some stuff $this->blocks = $this->_maketree($this->filecontents, ''); $this->filevar_parent = $this->_store_filevar_parents($this->blocks); $this->scan_globals(); } /** * assign a variable * * @example Simplest case: * @example $xtpl->assign('name', 'value'); * @example {name} in template * * @example Array assign: * @example $xtpl->assign(array('name' => 'value', 'name2' => 'value2')); * @example {name} {name2} in template * * @example Value as array assign: * @example $xtpl->assign('name', array('key' => 'value', 'key2' => 'value2')); * @example {name.key} {name.key2} in template * * @example Reset array: * @example $xtpl->assign('name', array('key' => 'value', 'key2' => 'value2')); * @example // Other code then: * @example $xtpl->assign('name', array('key3' => 'value3'), false); * @example {name.key} {name.key2} {name.key3} in template * * @access public * @param string $name Variable to assign $val to * @param string / array $val Value to assign to $name * @param boolean $reset_array Reset the variable array if $val is an array */ public function assign ($name, $val = '', $reset_array = true) { if (is_array($name)) { foreach ($name as $k => $v) { $this->vars[$k] = $v; } } elseif (is_array($val)) { // Clear the existing values if ($reset_array) { $this->vars[$name] = array(); } foreach ($val as $k => $v) { $this->vars[$name][$k] = $v; } } else { $this->vars[$name] = $val; } } /** * assign a file variable * * @access public * @param string $name Variable to assign $val to * @param string / array $val Values to assign to $name */ public function assign_file ($name, $val = '') { if (is_array($name)) { foreach ($name as $k => $v) { $this->_assign_file_sub($k, $v); } } else { $this->_assign_file_sub($name, $val); } } /** * parse a block * * @access public * @param string $bname Block name to parse */ public function parse ($bname) { if (isset($this->preparsed_blocks[$bname])) { $copy = $this->preparsed_blocks[$bname]; } elseif (isset($this->blocks[$bname])) { $copy = $this->blocks[$bname]; } elseif ($this->_ignore_missing_blocks) { // ------------------------------------------------------ // NW : 17 Oct 2002. Added default of ignore_missing_blocks // to allow for generalised processing where some // blocks may be removed from the HTML without the // processing code needing to be altered. // ------------------------------------------------------ // JRC: 3/1/2003 added set error to ignore missing functionality $this->_set_error("parse: blockname [$bname] does not exist"); return; } else { $this->_set_error("parse: blockname [$bname] does not exist"); } /* from there we should have no more {FILE } directives */ if (!isset($copy)) { die('Block: ' . $bname); } $copy = preg_replace($this->filevar_delim_nl, '', $copy); $var_array = array(); /* find & replace variables+blocks */ preg_match_all("|" . $this->tag_start_delim . "([A-Za-z0-9\._]+?" . $this->comment_preg . ")" . $this->tag_end_delim. "|", $copy, $var_array); $var_array = $var_array[1]; foreach ($var_array as $k => $v) { // Are there any comments in the tags {tag#a comment for documenting the template} $any_comments = explode('#', $v); $v = rtrim($any_comments[0]); if (sizeof($any_comments) > 1) { $comments = $any_comments[1]; } else { $comments = ''; } $sub = explode('.', $v); if ($sub[0] == '_BLOCK_') { unset($sub[0]); $bname2 = implode('.', $sub); // trinary operator eliminates assign error in E_ALL reporting $var = isset($this->parsed_blocks[$bname2]) ? $this->parsed_blocks[$bname2] : null; $nul = (!isset($this->_null_block[$bname2])) ? $this->_null_block[''] : $this->_null_block[$bname2]; if ($var === '') { if ($nul == '') { // ----------------------------------------------------------- // Removed requirement for blocks to be at the start of string // ----------------------------------------------------------- // $copy=preg_replace("/^\s*\{".$v."\}\s*\n*/m","",$copy); // Now blocks don't need to be at the beginning of a line, //$copy=preg_replace("/\s*" . $this->tag_start_delim . $v . $this->tag_end_delim . "\s*\n*/m","",$copy); $copy = preg_replace("|" . $this->tag_start_delim . $v . $this->tag_end_delim . "|m", '', $copy); } else { $copy = preg_replace("|" . $this->tag_start_delim . $v . $this->tag_end_delim . "|m", "$nul", $copy); } } else { //$var = trim($var); switch (true) { case preg_match('/^\n/', $var) && preg_match('/\n$/', $var): $var = substr($var, 1, -1); break; case preg_match('/^\n/', $var): $var = substr($var, 1); break; case preg_match('/\n$/', $var): $var = substr($var, 0, -1); break; } // SF Bug no. 810773 - thanks anonymous $var = str_replace('\\', '\\\\', $var); // Ensure dollars in strings are not evaluated reported by SadGeezer 31/3/04 $var = str_replace('$', '\\$', $var); // Replaced str_replaces with preg_quote //$var = preg_quote($var); $var = str_replace('\\|', '|', $var); $copy = preg_replace("|" . $this->tag_start_delim . $v . $this->tag_end_delim . "|m", "$var", $copy); if (preg_match('/^\n/', $copy) && preg_match('/\n$/', $copy)) { $copy = substr($copy, 1, -1); } } } else { $var = $this->vars; foreach ($sub as $v1) { // NW 4 Oct 2002 - Added isset and is_array check to avoid NOTICE messages // JC 17 Oct 2002 - Changed EMPTY to stlen=0 // if (empty($var[$v1])) { // this line would think that zeros(0) were empty - which is not true if (!isset($var[$v1]) || (!is_array($var[$v1]) && strlen($var[$v1]) == 0)) { // Check for constant, when variable not assigned if (defined($v1)) { $var[$v1] = constant($v1); } else { $var[$v1] = null; } } $var = $var[$v1]; } $nul = (!isset($this->_null_string[$v])) ? ($this->_null_string[""]) : ($this->_null_string[$v]); $var = (!isset($var)) ? $nul : $var; if ($var === '') { // ----------------------------------------------------------- // Removed requriement for blocks to be at the start of string // ----------------------------------------------------------- // $copy=preg_replace("|^\s*\{".$v." ?#?".$comments."\}\s*\n|m","",$copy); $copy = preg_replace("|" . $this->tag_start_delim . $v . "( ?#" . $comments . ")?" . $this->tag_end_delim . "|m", '', $copy); } $var = trim($var); // SF Bug no. 810773 - thanks anonymous $var = str_replace('\\', '\\\\', $var); // Ensure dollars in strings are not evaluated reported by SadGeezer 31/3/04 $var = str_replace('$', '\\$', $var); // Replace str_replaces with preg_quote //$var = preg_quote($var); $var = str_replace('\\|', '|', $var); $copy = preg_replace("|" . $this->tag_start_delim . $v . "( ?#" . $comments . ")?" . $this->tag_end_delim . "|m", "$var", $copy); if (preg_match('/^\n/', $copy) && preg_match('/\n$/', $copy)) { $copy = substr($copy, 1); } } } if (isset($this->parsed_blocks[$bname])) { $this->parsed_blocks[$bname] .= $copy; } else { $this->parsed_blocks[$bname] = $copy; } /* reset sub-blocks */ if ($this->_autoreset && (!empty($this->sub_blocks[$bname]))) { reset($this->sub_blocks[$bname]); foreach ($this->sub_blocks[$bname] as $k => $v) { $this->reset($v); } } } /** * returns the parsed text for a block, including all sub-blocks. * * @access public * @param string $bname Block name to parse */ public function rparse ($bname) { if (!empty($this->sub_blocks[$bname])) { reset($this->sub_blocks[$bname]); foreach ($this->sub_blocks[$bname] as $k => $v) { if (!empty($v)) { $this->rparse($v); } } } $this->parse($bname); } /** * inserts a loop ( call assign & parse ) * * @access public * @param string $bname Block name to assign * @param string $var Variable to assign values to * @param string / array $value Value to assign to $var */ public function insert_loop ($bname, $var, $value = '') { $this->assign($var, $value); $this->parse($bname); } /** * parses a block for every set of data in the values array * * @access public * @param string $bname Block name to loop * @param string $var Variable to assign values to * @param array $values Values to assign to $var */ public function array_loop ($bname, $var, &$values) { if (is_array($values)) { foreach($values as $v) { $this->insert_loop($bname, $var, $v); } } } /** * returns the parsed text for a block * * @access public * @param string $bname Block name to return * @return string */ public function text ($bname = '') { $text = ''; if ($this->debug && $this->output_type == 'HTML') { // JC 20/11/02 echo the template filename if in development as // html comment $text .= '\n"; } $bname = !empty($bname) ? $bname : $this->mainblock; $text .= isset($this->parsed_blocks[$bname]) ? $this->parsed_blocks[$bname] : $this->get_error(); return $text; } /** * prints the parsed text * * @access public * @param string $bname Block name to echo out */ public function out ($bname) { $out = $this->text($bname); // $length=strlen($out); //header("Content-Length: ".$length); // TODO: Comment this back in later echo $out; } /** * prints the parsed text to a specified file * * @access public * @param string $bname Block name to write out * @param string $fname File name to write to */ public function out_file ($bname, $fname) { if (!empty($bname) && !empty($fname) && is_writeable($fname)) { $fp = fopen($fname, 'w'); fwrite($fp, $this->text($bname)); fclose($fp); } } /** * resets the parsed text * * @access public * @param string $bname Block to reset */ public function reset ($bname) { $this->parsed_blocks[$bname] = ''; } /** * returns true if block was parsed, false if not * * @access public * @param string $bname Block name to test * @return boolean */ public function parsed ($bname) { return (!empty($this->parsed_blocks[$bname])); } /** * sets the string to replace in case the var was not assigned * * @access public * @param string $str Display string for null block * @param string $varname Variable name to apply $str to */ public function set_null_string($str, $varname = '') { $this->_null_string[$varname] = $str; } /** * Backwards compatibility only * * @param string $str * @param string $varname * @deprecated Change to set_null_string to keep in with rest of naming convention */ public function SetNullString ($str, $varname = '') { $this->set_null_string($str, $varname); } /** * sets the string to replace in case the block was not parsed * * @access public * @param string $str Display string for null block * @param string $bname Block name to apply $str to */ public function set_null_block ($str, $bname = '') { $this->_null_block[$bname] = $str; } /** * Backwards compatibility only * * @param string $str * @param string $bname * @deprecated Change to set_null_block to keep in with rest of naming convention */ public function SetNullBlock ($str, $bname = '') { $this->set_null_block($str, $bname); } /** * sets AUTORESET to 1. (default is 1) * if set to 1, parse() automatically resets the parsed blocks' sub blocks * (for multiple level blocks) * * @access public */ public function set_autoreset () { $this->_autoreset = true; } /** * sets AUTORESET to 0. (default is 1) * if set to 1, parse() automatically resets the parsed blocks' sub blocks * (for multiple level blocks) * * @access public */ public function clear_autoreset () { $this->_autoreset = false; } /** * scans global variables and assigns to PHP array * * @access public */ public function scan_globals () { reset($GLOBALS); foreach ($GLOBALS as $k => $v) { $GLOB[$k] = $v; } /** * Access global variables as: * @example {PHP._SERVER.HTTP_HOST} * in your template! */ $this->assign('PHP', $GLOB); } /** * gets error condition / string * * @access public * @return boolean / string */ public function get_error () { // JRC: 3/1/2003 Added ouptut wrapper and detection of output type for error message output $retval = false; if ($this->_error != '') { switch ($this->output_type) { case 'HTML': case 'html': $retval = '[XTemplate]
    ' . nl2br(str_replace('* ', '
  • ', str_replace(" *\n", "
  • \n", $this->_error))) . '
'; break; default: $retval = '[XTemplate] ' . str_replace(' *\n', "\n", $this->_error); break; } } return $retval; } /***************************************************************************/ /***[ private stuff ]*******************************************************/ /***************************************************************************/ /** * generates the array containing to-be-parsed stuff: * $blocks["main"],$blocks["main.table"],$blocks["main.table.row"], etc. * also builds the reverse parse order. * * @access public - aiming for private * @param string $con content to be processed * @param string $parentblock name of the parent block in the block hierarchy */ public function _maketree ($con, $parentblock='') { $blocks = array(); $con2 = explode($this->block_start_delim, $con); if (!empty($parentblock)) { $block_names = explode('.', $parentblock); $level = sizeof($block_names); } else { $block_names = array(); $level = 0; } // JRC 06/04/2005 Added block comments (on BEGIN or END) //$patt = "($this->block_start_word|$this->block_end_word)\s*(\w+)\s*$this->block_end_delim(.*)"; $patt = "(" . $this->block_start_word . "|" . $this->block_end_word . ")\s*(\w+)" . $this->comment_preg . "\s*" . $this->block_end_delim . "(.*)"; foreach($con2 as $k => $v) { $res = array(); if (preg_match_all("/$patt/ims", $v, $res, PREG_SET_ORDER)) { // $res[0][1] = BEGIN or END // $res[0][2] = block name // $res[0][3] = comment // $res[0][4] = kinda content $block_word = $res[0][1]; $block_name = $res[0][2]; $comment = $res[0][3]; $content = $res[0][4]; if (strtoupper($block_word) == $this->block_start_word) { $parent_name = implode('.', $block_names); // add one level - array("main","table","row") $block_names[++$level] = $block_name; // make block name (main.table.row) $cur_block_name=implode('.', $block_names); // build block parsing order (reverse) $this->block_parse_order[] = $cur_block_name; //add contents. trinary operator eliminates assign error in E_ALL reporting $blocks[$cur_block_name] = isset($blocks[$cur_block_name]) ? $blocks[$cur_block_name] . $content : $content; // add {_BLOCK_.blockname} string to parent block $blocks[$parent_name] .= str_replace('\\', '', $this->tag_start_delim) . '_BLOCK_.' . $cur_block_name . str_replace('\\', '', $this->tag_end_delim); // store sub block names for autoresetting and recursive parsing $this->sub_blocks[$parent_name][] = $cur_block_name; // store sub block names for autoresetting $this->sub_blocks[$cur_block_name][] = ''; } else if (strtoupper($block_word) == $this->block_end_word) { unset($block_names[$level--]); $parent_name = implode('.', $block_names); // add rest of block to parent block $blocks[$parent_name] .= $content; } } else { // no block delimiters found // Saves doing multiple implodes - less overhead $tmp = implode('.', $block_names); if ($k) { $blocks[$tmp] .= $this->block_start_delim; } // trinary operator eliminates assign error in E_ALL reporting $blocks[$tmp] = isset($blocks[$tmp]) ? $blocks[$tmp] . $v : $v; } } return $blocks; } /** * Sub processing for assign_file method * * @access private * @param string $name * @param string $val */ private function _assign_file_sub ($name, $val) { if (isset($this->filevar_parent[$name])) { if ($val != '') { $val = $this->_r_getfile($val); foreach($this->filevar_parent[$name] as $parent) { if (isset($this->preparsed_blocks[$parent]) && !isset($this->filevars[$name])) { $copy = $this->preparsed_blocks[$parent]; } elseif (isset($this->blocks[$parent])) { $copy = $this->blocks[$parent]; } $res = array(); preg_match_all($this->filevar_delim, $copy, $res, PREG_SET_ORDER); if (is_array($res) && isset($res[0])) { // Changed as per solution in SF bug ID #1261828 foreach ($res as $v) { // Changed as per solution in SF bug ID #1261828 if ($v[1] == $name) { // Changed as per solution in SF bug ID #1261828 $copy = preg_replace("/" . preg_quote($v[0]) . "/", "$val", $copy); $this->preparsed_blocks = array_merge($this->preparsed_blocks, $this->_maketree($copy, $parent)); $this->filevar_parent = array_merge($this->filevar_parent, $this->_store_filevar_parents($this->preparsed_blocks)); } } } } } } $this->filevars[$name] = $val; } /** * store container block's name for file variables * * @access public - aiming for private * @param array $blocks * @return array */ public function _store_filevar_parents ($blocks){ $parents = array(); foreach ($blocks as $bname => $con) { $res = array(); preg_match_all($this->filevar_delim, $con, $res); foreach ($res[1] as $k => $v) { $parents[$v][] = $bname; } } return $parents; } /** * Set the error string * * @access private * @param string $str */ private function _set_error ($str) { // JRC: 3/1/2003 Made to append the error messages $this->_error .= '* ' . $str . " *\n"; // JRC: 3/1/2003 Removed trigger error, use this externally if you want it eg. trigger_error($xtpl->get_error()) //trigger_error($this->get_error()); } /** * returns the contents of a file * * @access protected * @param string $file * @return string */ protected function _getfile ($file) { if (!isset($file)) { // JC 19/12/02 added $file to error message $this->_set_error('!isset file name!' . $file); return ''; } // check if filename is mapped to other filename if (isset($this->files)) { if (isset($this->files[$file])) { $file = $this->files[$file]; } } // prepend template dir if (!empty($this->tpldir)) { /** * Support hierarchy of file locations to search * * @example Supply array of filepaths when instantiating * First path supplied that has the named file is prioritised * $xtpl = new XTemplate('myfile.xtpl', array('.','/mypath', '/mypath2')); * @since 29/05/2007 */ if (is_array($this->tpldir)) { foreach ($this->tpldir as $dir) { if (is_readable($dir . DIRECTORY_SEPARATOR . $file)) { $file = $dir . DIRECTORY_SEPARATOR . $file; break; } } } else { $file = $this->tpldir. DIRECTORY_SEPARATOR . $file; } } $file_text = ''; if (isset($this->filecache[$file])) { $file_text .= $this->filecache[$file]; if ($this->debug) { $file_text = '' . "\n" . $file_text; } } else { if (is_file($file) && is_readable($file)) { if (filesize($file)) { if (!($fh = fopen($file, 'r'))) { $this->_set_error('Cannot open file: ' . realpath($file)); return ''; } $file_text .= fread($fh,filesize($file)); fclose($fh); } if ($this->debug) { $file_text = '' . "\n" . $file_text; } } elseif (str_replace('.', '', phpversion()) >= '430' && $file_text = @file_get_contents($file, true)) { // Enable use of include path by using file_get_contents // Implemented at suggestion of SF Feature Request ID #1529478 michaelgroh if ($file_text === false) { $this->_set_error("[" . realpath($file) . "] ($file) does not exist"); $file_text = "__XTemplate fatal error: file [$file] does not exist in the include path__"; } elseif ($this->debug) { $file_text = '' . "\n" . $file_text; } } elseif (!is_file($file)) { // NW 17 Oct 2002 : Added realpath around the file name to identify where the code is searching. $this->_set_error("[" . realpath($file) . "] ($file) does not exist"); $file_text .= "__XTemplate fatal error: file [$file] does not exist__"; } elseif (!is_readable($file)) { $this->_set_error("[" . realpath($file) . "] ($file) is not readable"); $file_text .= "__XTemplate fatal error: file [$file] is not readable__"; } $this->filecache[$file] = $file_text; } return $file_text; } /** * recursively gets the content of a file with {FILE "filename.tpl"} directives * * @access public - aiming for private * @param string $file * @return string */ public function _r_getfile ($file) { $text = $this->_getfile($file); $res = array(); while (preg_match($this->file_delim,$text,$res)) { $text2 = $this->_getfile($res[1]); $text = preg_replace("'".preg_quote($res[0])."'",$text2,$text); } return $text; } /** * add an outer block delimiter set useful for rtfs etc - keeps them editable in word * * @access private */ private function _add_outer_block () { $before = $this->block_start_delim . $this->block_start_word . ' ' . $this->mainblock . ' ' . $this->block_end_delim; $after = $this->block_start_delim . $this->block_end_word . ' ' . $this->mainblock . ' ' . $this->block_end_delim; $this->filecontents = $before . "\n" . $this->filecontents . "\n" . $after; } /** * Debug function - var_dump wrapped in '
' tags
     *
     * @access private
     * @param multiple var_dumps all the supplied arguments
     */
	private function _pre_var_dump ($args) {

		if ($this->debug) {
			echo '
';
			var_dump(func_get_args());
			echo '
'; } } } /* end of XTemplate class. */ ?>simpleid/www/extensions/0000755000175000017500000000000011710103552015154 5ustar danieldanielsimpleid/www/extensions/ui/0000755000175000017500000000000011746513200015575 5ustar danieldanielsimpleid/www/extensions/ui/ui.css0000644000175000017500000000164011710103700016714 0ustar danieldaniel/* * SimpleID * * Copyright (C) Kelvin Mo 2009 * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: ui.css 487 2011-12-15 12:19:15Z kmo $ */ .dialog-page { background: #FFFFFF; } .dialog-page #content { margin: 10px auto; padding: 0; border: 0; } simpleid/www/extensions/ui/ui.extension.inc0000644000175000017500000001747011710103700020720 0ustar danieldanielassign('icon_url', htmlspecialchars($icon_url, ENT_QUOTES, 'UTF-8')); $xtpl->parse('main.openid_consent.icon'); } return ''; } /** * Specifies that the OpenID response should be sent via the fragment * */ function ui_indirect_response($url, $response) { global $openid_ns_to_alias; if (!array_key_exists(OPENID_NS_UI, $openid_ns_to_alias)) return NULL; // Cheat - if we run this, then the redirect page will also be themed! _ui_insert_css_js(); if (strstr($url, '#')) { return OPENID_RESPONSE_FRAGMENT; } else { return NULL; } } /** * Adds an extra route to the SimpleWeb framework. */ function ui_routes() { return array('ui/icon' => 'ui_icon'); } /** * Returns an icon. */ function ui_icon() { if (!isset($_GET['realm']) || !isset($_GET['tk']) || ($_GET['tk'] != _ui_icon_token($_GET['realm']))) { header('HTTP/1.1 404 Not Found'); indirect_fatal_error('Invalid UI icon parameters.'); } $realm = $_GET['realm']; $icon_res = _ui_get_icon($realm); if ($icon_res === NULL) { header('HTTP/1.1 404 Not Found'); indirect_fatal_error('Unable to get icon.'); } header('Via: ' . $icon_res['protocol'] . ' simpleid-ui-icon-' . md5($realm)); header('Cache-Control: max-age=86400'); header('Content-Type: ' . $icon_res['headers']['content-type']); if (isset($icon_res['headers']['content-encoding'])) header('Content-Encoding: ' . $icon_res['headers']['content-encoding']); print $icon_res['data']; } /** * Inserts the necessary CSS and JavaScript code to implement the popup mode * from the User Interface extension. */ function _ui_insert_css_js() { global $xtpl; $css = (isset($xtpl->vars['css'])) ? $xtpl->vars['css'] : ''; $js = (isset($xtpl->vars['javascript'])) ? $xtpl->vars['javascript'] : ''; $xtpl->assign('css', $css . '@import url(' . get_base_path() . 'extensions/ui/ui.css);'); $xtpl->assign('javascript', $js . ''); } /** * Attempts to obtain an icon from a RP * * @param string $realm the openid.realm parameter * @return array the response from {@link http_make_request()} with the discovered URL of the * RP's icon */ function _ui_get_icon($realm) { $rp_info = simpleid_get_rp_info($realm); if (isset($rp_info['ui_icon'])) return $rp_info['ui_icon']; $services = discovery_get_service_by_type($rp_info['services'], 'http://specs.openid.net/extensions/ui/icon'); if ($services) { $icon_url = $services[0]['uri']; $icon_res = http_make_request($icon_url); if (isset($icon_res['http-error'])) { return NULL; } $rp_info['ui_icon'] = $icon_res; simpleid_set_rp_info($realm, $rp_info); } else { return NULL; } } /** * Returns a token to be used when requesting the icon. * * The token is used to prevent flooding SimpleID with external requests. * * @param string $realm the openid.realm parameter * @return string the token */ function _ui_icon_token($realm) { return get_form_token('q=ui/icon&realm=' . rawurlencode($realm)); } ?> simpleid/www/extensions/ui/ui.js0000644000175000017500000000072011710103700016536 0ustar danieldaniel/* * SimpleID * * Copyright (C) Kelvin Mo 2009 * * This program is licensed under the GPL. * * $Id: ui.js 487 2011-12-15 12:19:15Z kmo $ */ $(document).ready(function() { $('input#edit-cancel').click(function() { window.close(); return false; }); $(document).keydown(function(e) { if (e.which == 27) { // Close the window if user presses Esc window.close(); return false; } }); }); simpleid/www/extensions/ax/0000755000175000017500000000000011746513177015605 5ustar danieldanielsimpleid/www/extensions/ax/ax.xtpl0000644000175000017500000000257711710103700017113 0ustar danieldaniel

SimpleID will send the following information to sites which supports the Attribute Exchange Extension. If you also have the Simple Registration Extension installed, these may also be sent as part of this Extension.

To change these, or your password, edit your identity file.

Type URL Value
{name} {value}

SimpleID will also be sending the following information to the site.

Type URL Value
{name} {value}

This web site requested to store information about you on SimpleID. Sadly, SimpleID does not support this feature.

simpleid/www/extensions/ax/ax.extension.inc0000644000175000017500000001754111710103700020705 0ustar danieldaniel 'nickname', 'http://axschema.org/contact/email' => 'email', 'http://axschema.org/namePerson' => 'fullname', 'http://axschema.org/birthDate' => 'dob', 'http://axschema.org/person/gender' => 'gender', 'http://axschema.org/contact/postalCode/home' => 'postcode', 'http://axschema.org/contact/country/home' => 'country', 'http://axschema.org/pref/language' => 'language', 'http://axschema.org/pref/timezone' => 'timezone', 'http://openid.net/schema/namePerson/friendly' => 'nickname', 'http://openid.net/schema/contact/internet/email' => 'email', 'http://openid.net/schema/gender' => 'gender', 'http://openid.net/schema/contact/postalCode/home' => 'postcode', 'http://openid.net/schema/contact/country/home' => 'country', 'http://openid.net/schema/language/pref' => 'language', 'http://openid.net/schema/timezone' => 'timezone' ); /** * Returns the support for AX in SimpleID XRDS document * * @return array * @see hook_xrds_types() */ function ax_xrds_types() { return array(OPENID_NS_AX); } /** * @see hook_response() */ function ax_response($assertion, $request) { global $user; global $version; global $ax_sreg_map; // We only deal with positive assertions if (!$assertion) return array(); // We only respond if the extension is requested if (!openid_extension_requested(OPENID_NS_AX, $request)) return array(); $request = openid_extension_filter_request(OPENID_NS_AX, $request); if (!isset($request['mode'])) return array(); $mode = $request['mode']; $response = array(); $alias = openid_extension_alias(OPENID_NS_AX); $response['openid.ns.' . $alias] = OPENID_NS_AX; if ($mode == 'fetch_request') { $response['openid.' . $alias . '.mode'] = 'fetch_response'; $required = (isset($request['required'])) ? explode(',', $request['required']) : array(); $optional = (isset($request['if_available'])) ? explode(',', $request['if_available']) : array(); $fields = array_merge($required, $optional); foreach ($fields as $field) { $type = $request['type.' . $field]; $response['openid.' . $alias . '.type.' . $field] = $type; $value = _ax_get_value($type); if ($value == NULL) { $response['openid.' . $alias . '.count.' . $field] = 0; } elseif (is_array($value)) { $response['openid.' . $alias . '.count.' . $field] = count($value); for ($i = 0; $i < count($value); $i++) { $response['openid.' . $alias . '.value.' . $field . '.' . ($i + 1)] = $value[$i]; } } else { $response['openid.' . $alias . '.value.' . $field] = $value; } } } elseif ($mode == 'store_request') { // Sadly, we don't support storage at this stage $response['openid.' . $alias . '.mode'] = 'store_response_failure'; $response['openid.' . $alias . '.error'] = 'OpenID provider does not support storage of attributes'; } return $response; } /** * Returns an array of fields that need signing. * * @see hook_signed_fields() */ function ax_signed_fields($response) { // We only respond if the extension is requested if (!openid_extension_requested(OPENID_NS_AX, $response)) return array(); $fields = array_keys(openid_extension_filter_request(OPENID_NS_AX, $response)); $alias = openid_extension_alias(OPENID_NS_AX); $signed_fields = array(); if (isset($response['openid.ns.' . $alias])) $signed_fields[] = 'ns.' . $alias; foreach ($fields as $field) { if (isset($response['openid.' . $alias . '.' . $field])) $signed_fields[] = $alias . '.' . $field; } return $signed_fields; } /** * @see hook_consent_form() */ function ax_consent_form($request, $response, $rp) { global $user; // We only respond if the extension is requested if (!openid_extension_requested(OPENID_NS_AX, $request)) return ''; $request = openid_extension_filter_request(OPENID_NS_AX, $request); if (!isset($request['mode'])) return ''; $mode = $request['mode']; $xtpl2 = new XTemplate('extensions/ax/ax.xtpl'); if ($mode == 'fetch_request') { $xtpl2->assign('alias', openid_extension_alias(OPENID_NS_AX)); $required = (isset($request['required'])) ? explode(',', $request['required']) : array(); $optional = (isset($request['if_available'])) ? explode(',', $request['if_available']) : array(); $fields = array_merge($required, $optional); foreach ($fields as $field) { $type = $request['type.' . $field]; $value = _ax_get_value($type); if (is_array($value)) { $xtpl2->assign('name', htmlspecialchars($type, ENT_QUOTES, 'UTF-8')); $xtpl2->assign('value', htmlspecialchars(implode(',', $value), ENT_QUOTES, 'UTF-8')); $xtpl2->parse('fetch_request.ax'); } elseif ($value != NULL) { $xtpl2->assign('name', htmlspecialchars($type, ENT_QUOTES, 'UTF-8')); $xtpl2->assign('value', htmlspecialchars($value, ENT_QUOTES, 'UTF-8')); $xtpl2->parse('fetch_request.ax'); } } $xtpl2->parse('fetch_request'); return $xtpl2->text('fetch_request'); } elseif ($mode == 'store_request') { // Sadly, we don't support storage at this stage $xtpl2->parse('store_request'); return $xtpl2->text('store_request'); } } /** * @see hook_page_profile() */ function ax_page_profile() { global $user; $xtpl2 = new XTemplate('extensions/ax/ax.xtpl'); if (isset($user['ax'])) { foreach ($user['ax'] as $name => $value) { $xtpl2->assign('name', htmlspecialchars($name, ENT_QUOTES, 'UTF-8')); $xtpl2->assign('value', htmlspecialchars($value, ENT_QUOTES, 'UTF-8')); $xtpl2->parse('user_page.ax'); } } $xtpl2->parse('user_page'); return array(array( 'id' => 'ax', 'title' => 'Attribute Exchange Extension', 'content' => $xtpl2->text('user_page') )); } function _ax_get_value($type) { global $user; global $ax_sreg_map; if (isset($user['ax'][$type])) { return $user['ax'][$type]; } elseif (isset($ax_sreg_map[$type]) && isset($user['sreg'][$ax_sreg_map[$type]])) { return $user['sreg'][$ax_sreg_map[$type]]; } else { return NULL; } } ?> simpleid/www/extensions/sreg/0000755000175000017500000000000011746513177016135 5ustar danieldanielsimpleid/www/extensions/sreg/sreg.extension.inc0000644000175000017500000001240311710103700021555 0ustar danieldaniel * James Walker * * Copyright (C) Rowan Kerr and James Walker * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: sreg.extension.inc 487 2011-12-15 12:19:15Z kmo $ */ /** * Implements the Simple Registration extension. * * * @package simpleid * @subpackage extensions * @filesource */ /** * @see hook_response() */ function sreg_response($assertion, $request) { global $user; global $version; // We only deal with positive assertions if (!$assertion) return array(); // We only respond if the extension is requested if (!openid_extension_requested('http://openid.net/extensions/sreg/1.1', $request)) return array(); $request = openid_extension_filter_request('http://openid.net/extensions/sreg/1.1', $request); $required = (isset($request['required'])) ? explode(',', $request['required']) : array(); $optional = (isset($request['optional'])) ? explode(',', $request['optional']) : array(); $fields = array_merge($required, $optional); $alias = openid_extension_alias('http://openid.net/extensions/sreg/1.1'); $response = array(); if ($version == OPENID_VERSION_2) $response['openid.ns.' . $alias] = 'http://openid.net/extensions/sreg/1.1'; foreach ($fields as $field) { if (isset($user['sreg'][$field])) { $response['openid.' . $alias . '.' . $field] = $user['sreg'][$field]; } } return $response; } /** * Returns an array of fields that need signing. * * @see hook_signed_fields() */ function sreg_signed_fields($response) { // We only respond if the extension is requested if (!openid_extension_requested('http://openid.net/extensions/sreg/1.1', $response)) return array(); $fields = array_keys(openid_extension_filter_request('http://openid.net/extensions/sreg/1.1', $response)); $alias = openid_extension_alias('http://openid.net/extensions/sreg/1.1'); $signed_fields = array(); if (isset($response['openid.ns.' . $alias])) $signed_fields[] = 'ns.' . $alias; foreach ($fields as $field) { if (isset($response['openid.' . $alias . '.' . $field])) $signed_fields[] = $alias . '.' . $field; } return $signed_fields; } /** * @see hook_consent_form() */ function sreg_consent_form($request, $response, $rp) { global $user; // We only respond if the extension is requested if (!openid_extension_requested('http://openid.net/extensions/sreg/1.1', $request)) return ''; $request = openid_extension_filter_request('http://openid.net/extensions/sreg/1.1', $request); $required = (isset($request['required'])) ? explode(',', $request['required']) : array(); $optional = (isset($request['optional'])) ? explode(',', $request['optional']) : array(); $keys = array_merge($required, $optional); if ((count($request)) && isset($user['sreg'])) { $xtpl2 = new XTemplate('extensions/sreg/sreg.xtpl'); $xtpl2->assign('alias', openid_extension_alias('http://openid.net/extensions/sreg/1.1')); if (isset($request['policy_url'])) { $xtpl2->assign('policy', 'You can view the site\'s policy in relation to the use of this information at this URL: ' . htmlspecialchars($request['policy_url'], ENT_QUOTES, 'UTF-8') . '.'); } foreach ($keys as $key) { if (isset($user['sreg'][$key])) { $xtpl2->assign('name', htmlspecialchars($key, ENT_QUOTES, 'UTF-8')); $xtpl2->assign('value', htmlspecialchars($user['sreg'][$key], ENT_QUOTES, 'UTF-8')); $xtpl2->parse('form.sreg'); } } $xtpl2->parse('form'); return $xtpl2->text('form'); } } /** * @see hook_page_profile() */ function sreg_page_profile() { global $user; $xtpl2 = new XTemplate('extensions/sreg/sreg.xtpl'); if (isset($user['sreg'])) { foreach ($user['sreg'] as $name => $value) { $xtpl2->assign('name', htmlspecialchars($name, ENT_QUOTES, 'UTF-8')); $xtpl2->assign('value', htmlspecialchars($value, ENT_QUOTES, 'UTF-8')); $xtpl2->parse('user_page.sreg'); } } $xtpl2->parse('user_page'); return array(array( 'id' => 'sreg', 'title' => 'Simple Registration Extension', 'content' => $xtpl2->text('user_page') )); } ?> simpleid/www/extensions/sreg/sreg.xtpl0000644000175000017500000000220011710103700017752 0ustar danieldaniel

SimpleID will send the following information to sites which supports the Simple Registration Extension.

To change these, or your password, edit your identity file.

Name Value
{name} {value}

SimpleID will also be sending the following registration information to the site. {policy}

Name Value
{name} {value}
simpleid/www/extensions/pape/0000755000175000017500000000000011746513177016122 5ustar danieldanielsimpleid/www/extensions/pape/pape.extension.inc0000644000175000017500000001542711710103700021540 0ustar danieldaniel $pape_request['max_auth_age'])) { set_message('This web site\'s policy requires you to log in again to confirm your identity.'); _user_logout(); return CHECKID_LOGIN_REQUIRED; } } } /** * @see hook_response() */ function pape_response($assertion, $request) { global $user, $version; // We only deal with positive assertions if (!$assertion) return array(); // We only respond if we are using OpenID 2 or later if ($version < OPENID_VERSION_2) return array(); // Get what is requested $pape_request = openid_extension_filter_request(OPENID_NS_PAPE, $request); // If the extension is requested, we use the same alias, otherwise, we // make one up $alias = openid_extension_alias(OPENID_NS_PAPE, 'pape'); $response = array(); // The PAPE specification recommends us to respond even when the extension // is not present in the request. $response['openid.ns.' . $alias] = OPENID_NS_PAPE; // We return the last time the user logged in using the login form $response['openid.' . $alias . '.auth_time'] = gmstrftime('%Y-%m-%dT%H:%M:%SZ', $user['auth_time']); // We don't comply with NIST_SP800-63 $response['openid.' . $alias . '.auth_level.ns.nist'] = PAPE_LEVEL_NIST800_63; $response['openid.' . $alias . '.auth_level.nist'] = 0; // The default is that we don't apply any authentication policies. This can be changed later in the // function $response['openid.' . $alias . '.auth_policies'] = PAPE_POLICY_NONE; // Now we go through the authentication policies if (isset($pape_request['preferred_auth_policies'])) { $policies = preg_split('/\s+/', $pape_request['preferred_auth_policies']); if (in_array(PAPE_POLICY_PPID, $policies)) { // We want a ppid. Check that the authentication request is correct if (_pape_identifier_select()) { $realm = openid_get_realm($request, $version); $identity = $request['openid.identity']; $ppid = _pape_ppid($identity, $realm); $response['openid.claimed_id'] = $ppid; $response['openid.identity'] = $ppid; } } } return $response; } /** * Returns an array of fields that need signing. * * @see hook_signed_fields() */ function pape_signed_fields($response) { $fields = array_keys(openid_extension_filter_request(OPENID_NS_PAPE, $response)); $alias = openid_extension_alias(OPENID_NS_PAPE); $signed_fields = array(); if (isset($response['openid.ns.' . $alias])) $signed_fields[] = 'ns.' . $alias; foreach ($fields as $field) { if (isset($response['openid.' . $alias . '.' . $field])) $signed_fields[] = $alias . '.' . $field; } return $signed_fields; } /** * Sets and returns whether the current OpenID request is requesting an identity. * * @param bool $identifier_select * @return bool whether the current OpenID request is requesting an identity */ function _pape_identifier_select($identifier_select = NULL) { static $static_identifier_select = false; if (!is_null($identifier_select)) $static_identifier_select = $identifier_select; return $static_identifier_select; } /** * Generates a private personal identifier (PPID). The PPID is an opaque identifier * for a particular user-RP pair * * @param string $identity the identity of the user * @param string $realm the URL of the relying party * @return string the PPID */ function _pape_ppid($identity, $realm) { // We are reusing the site-token from get_form_token() in common.inc if (store_get('site-token') == NULL) { $site_token = mt_rand(); store_set('site-token', $site_token); } else { $site_token = store_get('site-token'); } $parts = parse_url($realm); $host = $parts['host']; if (strstr($host, 'www.') === 0) $host = substr($host, 4); return simpleid_url('ppid/' . md5($site_token . $identity . $host)); } ?> simpleid/www/index.php0000644000175000017500000012705411710103700014601 0ustar danieldaniel * James Walker * * Copyright (C) Rowan Kerr and James Walker * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: index.php 484 2011-12-15 10:49:31Z kmo $ */ /** * Main SimpleID file. * * @package simpleid * @filesource */ include_once "version.inc"; include_once "config.inc"; include_once "config.default.inc"; include_once "log.inc"; include_once "common.inc"; include_once "simpleweb.inc"; include_once "openid.inc"; include_once "discovery.inc"; include_once "user.inc"; include_once "cache.inc"; include_once SIMPLEID_STORE . ".store.inc"; include_once "page.inc"; // Allow for PHP5 version of xtemplate if (version_compare(PHP_VERSION, '5.0.0') === 1) { include "lib/xtemplate.class.php"; } else { include "lib/xtemplate-php4.class.php"; } define('CACHE_DIR', SIMPLEID_CACHE_DIR); /** */ define('CHECKID_OK', 127); define('CHECKID_RETURN_TO_SUSPECT', 3); define('CHECKID_APPROVAL_REQUIRED', 2); define('CHECKID_LOGIN_REQUIRED', -1); define('CHECKID_IDENTITIES_NOT_MATCHING', -2); define('CHECKID_IDENTITY_NOT_EXIST', -3); define('CHECKID_PROTOCOL_ERROR', -127); define('ASSOCIATION_PRIVATE', 2); define('ASSOCIATION_SHARED', 1); /** * This variable holds the version of the OpenID specification associated with * the current OpenID request. This can be either {@link OPENID_VERSION_1_1} * or {@link OPENID_VERSION_2}. * * @global float $version */ $version = OPENID_VERSION_1_1; /** * This variable holds an instance of the XTemplate engine. * * @global object $xtpl */ $xtpl = NULL; /** * This variable holds the combined $_GET and $_POST superglobal arrays. * This is then passed through {@link openid_fix_request()}. * * @global array $GETPOST */ $GETPOST = array(); simpleid_start(); /** * Entry point for SimpleID. * * @see user_init() */ function simpleid_start() { global $xtpl, $GETPOST; $xtpl = new XTemplate('html/template.xtpl'); $xtpl->assign('version', SIMPLEID_VERSION); $xtpl->assign('base_path', get_base_path()); // Check if the configuration file has been defined if (!defined('SIMPLEID_BASE_URL')) { log_fatal('No configuration file found.'); indirect_fatal_error('No configuration file found. See the manual for instructions on how to set up a configuration file.'); } if (!is_dir(SIMPLEID_IDENTITIES_DIR)) { log_fatal('Identities directory not found.'); indirect_fatal_error('Identities directory not found. See the manual for instructions on how to set up SimpleID.'); } if (!is_dir(SIMPLEID_CACHE_DIR) || !is_writeable(SIMPLEID_CACHE_DIR)) { log_fatal('Cache directory not found or not writeable.'); indirect_fatal_error('Cache directory not found or not writeable. See the manual for instructions on how to set up SimpleID.'); } if (!is_dir(SIMPLEID_STORE_DIR) || !is_writeable(SIMPLEID_STORE_DIR)) { log_fatal('Store directory not found or not writeable.'); indirect_fatal_error('Store directory not found or not writeable. See the manual for instructions on how to set up SimpleID.'); } if ((@ini_get('register_globals') === 1) || (@ini_get('register_globals') === '1') || (strtolower(@ini_get('register_globals')) == 'on')) { log_fatal('register_globals is enabled in PHP configuration.'); indirect_fatal_error('register_globals is enabled in PHP configuration, which is not supported by SimpleID. See the manual for further information.'); } openid_fix_request(); $GETPOST = array_merge($_GET, $_POST); $q = (isset($GETPOST['q'])) ? $GETPOST['q'] : ''; extension_init(); user_init($q); log_info('Session opened for "' . $q . '" [' . $_SERVER['REMOTE_ADDR'] . ', ' . gethostbyaddr($_SERVER['REMOTE_ADDR']) . ']'); // Clean stale assocations cache_gc(SIMPLEID_ASSOC_EXPIRES_IN, 'association'); cache_gc(300, 'stateless'); simpleid_route($q); } /** * Dispatches to the correct SimpleID function based on the request path. The * request path usually comes from the q parameter in the query string (which may * be inserted by mod_rewrite), but can come from other functions as well. * * @param string $q the request path */ function simpleid_route($q) { $routes = array( 'continue' => 'simpleid_continue', 'login' => 'user_login', 'logout' => 'user_logout', 'my/dashboard' => 'page_dashboard', 'my/sites' => 'page_sites', 'my/profile' => 'page_profile', 'openid/consent' => 'simpleid_openid_consent', 'ppid/(.*)' => 'user_ppid_page', 'user' => 'user_public_page', 'user/(.+)' => 'user_public_page', 'xrds/(.*)' => 'user_xrds', 'xrds' => 'simpleid_xrds', ); $routes = array_merge($routes, extension_invoke_all('routes'), array('.*' => 'simpleid_index')); simpleweb_run($routes, $q); } /** * The default route, called when the q parameter is missing or is invalid. * * This function performs the following: * * - If openid.mode is present, then the request is an OpenID request. This * is passed to {@link simpleid_process_openid()} * - If the Accept HTTP header contains the expression application/xrds+xml, then * the request is a YADIS discovery request for SimpleID as an OpenID provider. Thi * is passed to {@link simpleid_xrds()} * - Otherwise, the dashboard or the login page is displayed to the user as * appropriate * */ function simpleid_index() { global $GETPOST; log_debug('simpleid_index'); $content_type = negotiate_content_type(array('text/html', 'application/xml', 'application/xhtml+xml', 'application/xrds+xml')); header('Vary: Accept'); if (isset($GETPOST['openid.mode'])) { simpleid_process_openid($GETPOST); return; } elseif ($content_type == 'application/xrds+xml') { simpleid_xrds(); } else { // Point to SimpleID's XRDS document header('X-XRDS-Location: ' . simpleid_url('xrds')); page_dashboard(); } } /** * Process an OpenID request. * * This function determines the version of the OpenID specification that is * relevant to this request, checks openid.mode and passes the * request on to the function required to process the request. * * The OpenID request expressed as an array contain key-value pairs corresponding * to the HTTP request. This is usually contained in the $_REQUEST * variable. * * @param array $request the OpenID request */ function simpleid_process_openid($request) { global $version; $version = openid_get_version($request); switch ($request['openid.mode']) { case 'associate': simpleid_associate($request); return; case 'checkid_immediate': case 'checkid_setup': return simpleid_checkid($request); case 'check_authentication': simpleid_check_authentication($request); break; default: if (isset($request['openid.return_to'])) { // Indirect communication - send error via indirect communication. header('HTTP/1.1 400 Bad Request'); set_message('Invalid OpenID message.'); page_dashboard(); } else { // Direct communication openid_direct_error('Invalid OpenID message.'); } } } /** * Processes an association request from a relying party. * * An association request has an openid.mode value of * associate. This function checks whether the association request * is valid, and if so, creates an association and sends the response to * the relying party. * * @see _simpleid_create_association() * @param array $request the OpenID request * @link http://openid.net/specs/openid-authentication-1_1.html#mode_associate, http://openid.net/specs/openid-authentication-2_0.html#associations * */ function simpleid_associate($request) { global $version; log_info('OpenID association request: ' . log_array($request)); $assoc_types = openid_association_types(); $session_types = openid_session_types(is_https(), $version); // Common Request Parameters [8.1.1] if (($version == OPENID_VERSION_1_1) && !isset($request['openid.session_type'])) $request['openid.session_type'] = ''; $assoc_type = $request['openid.assoc_type']; $session_type = $request['openid.session_type']; // Diffie-Hellman Request Parameters [8.1.2] $dh_modulus = (isset($request['openid.dh_modulus'])) ? $request['openid.dh_modulus'] : NULL; $dh_gen = (isset($request['openid.dh_gen'])) ? $request['openid.dh_gen'] : NULL; $dh_consumer_public = $request['openid.dh_consumer_public']; if (!isset($request['openid.session_type']) || !isset($request['openid.assoc_type'])) { log_error('Association failed: openid.session_type or openid.assoc_type not set'); openid_direct_error('openid.session_type or openid.assoc_type not set'); return; } // Check if the assoc_type is supported if (!array_key_exists($assoc_type, $assoc_types)) { $error = array( 'error_code' => 'unsupported-type', 'session_type' => 'DH-SHA1', 'assoc_type' => 'HMAC-SHA1' ); log_error('Association failed: The association type is not supported by SimpleID.'); openid_direct_error('The association type is not supported by SimpleID.', $error, $version); return; } // Check if the session_type is supported if (!array_key_exists($session_type, $session_types)) { $error = array( 'error_code' => 'unsupported-type', 'session_type' => 'DH-SHA1', 'assoc_type' => 'HMAC-SHA1' ); log_error('Association failed: The session type is not supported by SimpleID.'); openid_direct_error('The session type is not supported by SimpleID.', $error, $version); return; } if ($session_type == 'DH-SHA1' || $session_type == 'DH-SHA256') { if (!$dh_consumer_public) { log_error('Association failed: openid.dh_consumer_public not set'); openid_direct_error('openid.dh_consumer_public not set'); return; } } $response = _simpleid_create_association(ASSOCIATION_SHARED, $assoc_type, $session_type, $dh_modulus, $dh_gen, $dh_consumer_public); openid_direct_response(openid_direct_message($response, $version)); } /** * Creates an association. * * This function calls {@link openid_dh_server_assoc()} where required, to * generate the cryptographic values required for an association response. * * @param int $mode either ASSOCIATION_SHARED or ASSOCIATION_PRIVATE * @param string $assoc_type a valid OpenID association type * @param string $session_type a valid OpenID session type * @param string $dh_modulus for Diffie-Hellman key exchange, the modulus encoded in Base64 * @param string $dh_gen for Diffie-Hellman key exchange, g encoded in Base64 * @param string $dh_consumer_public for Diffie-Hellman key exchange, the public key of the relying party encoded in Base64 * @return mixed if $mode is ASSOCIATION_SHARED, an OpenID response * to the association request, if $mode is ASSOCIATION_PRIVATE, the * association data for storage. * @link http://openid.net/specs/openid-authentication-1_1.html#anchor14, http://openid.net/specs/openid-authentication-2_0.html#anchor20 */ function _simpleid_create_association($mode = ASSOCIATION_SHARED, $assoc_type = 'HMAC-SHA1', $session_type = 'no-encryption', $dh_modulus = NULL, $dh_gen = NULL, $dh_consumer_public = NULL) { global $version; $assoc_types = openid_association_types(); $session_types = openid_session_types(is_https(), $version); $mac_size = $assoc_types[$assoc_type]['mac_size']; $hmac_func = $assoc_types[$assoc_type]['hmac_func']; $assoc_handle = random_id(); $expires_in = SIMPLEID_ASSOC_EXPIRES_IN; $secret = random_bytes($mac_size); $response = array( 'assoc_handle' => $assoc_handle, 'assoc_type' => $assoc_type, 'expires_in' => $expires_in ); // If $session_type is '', then it must be using OpenID 1.1 (blank parameter // is not allowed for OpenID 2.0. For OpenID 1.1 blank requests, we don't // put a session_type in the response. if ($session_type != '') $response['session_type'] = $session_type; if (($session_type == 'no-encryption') || ($session_type == '')) { $mac_key = base64_encode(call_user_func($hmac_func, $secret, $response['assoc_handle'])); $response['mac_key'] = $mac_key; } elseif ($session_type == 'DH-SHA1' || $session_type == 'DH-SHA256') { $hash_func = $session_types[$session_type]['hash_func']; $dh_assoc = openid_dh_server_assoc($secret, $dh_consumer_public, $dh_modulus, $dh_gen, $hash_func); $mac_key = base64_encode($secret); $response['dh_server_public'] = $dh_assoc['dh_server_public']; $response['enc_mac_key'] = $dh_assoc['enc_mac_key']; } $association = array('assoc_handle' => $assoc_handle, 'assoc_type' => $assoc_type, 'mac_key' => $mac_key, 'created' => time()); if ($mode == ASSOCIATION_PRIVATE) $association['private'] = 1; cache_set('association', $assoc_handle, $association); if ($mode == ASSOCIATION_SHARED) { log_info('Created association: ' . log_array($response)); log_debug('***** MAC key: ' . $association['mac_key']); return $response; } else { log_info('Created association: private; ' . log_array($association, array('assoc_handle', 'assoc_type'))); log_debug('***** MAC key: ' . $association['mac_key']); return $association; } } /** * Processes an authentication request from a relying party. * * An authentication request has an openid.mode value of * checkid_setup or checkid_immediate. * * If the authentication request is a standard OpenID request about an identity * (i.e. contains the key openid.identity), this function calls * {@link simpleid_checkid_identity()} to see whether the user logged on into SimpleID * matches the identity supplied in the OpenID request. * * If the authentication request is not about an identity, this function calls * the {@link hook_checkid() checkid hook} of the loaded extensions. * * Depending on the OpenID version, this function will supply an appropriate * assertion. * * @param array $request the OpenID request * */ function simpleid_checkid($request) { global $version; $immediate = ($request['openid.mode'] == 'checkid_immediate'); log_info('OpenID authentication request: ' . (($immediate) ? 'immediate' : 'setup') . '; '. log_array($request)); // Check for protocol correctness if ($version == OPENID_VERSION_1_1) { if (!isset($request['openid.return_to'])) { log_error('Protocol Error: openid.return_to not set.'); indirect_fatal_error('Protocol Error: openid.return_to not set.'); return; } if (!isset($request['openid.identity'])) { log_error('Protocol Error: openid.identity not set.'); indirect_fatal_error('Protocol Error: openid.identity not set.'); return; } } if ($version >= OPENID_VERSION_2) { if (isset($request['openid.identity']) && !isset($request['openid.claimed_id'])) { log_error('Protocol Error: openid.identity set, but not openid.claimed_id.'); indirect_fatal_error('Protocol Error: openid.identity set, but not openid.claimed_id.'); return; } if (!isset($request['openid.realm']) && !isset($request['openid.return_to'])) { log_error('Protocol Error: openid.return_to not set when openid.realm is not set.'); indirect_fatal_error('Protocol Error: openid.return_to not set when openid.realm is not set.'); return; } } if (isset($request['openid.return_to'])) { $realm = openid_get_realm($request, $version); if (!openid_url_matches_realm($request['openid.return_to'], $realm)) { log_error('Protocol Error: openid.return_to does not match realm.'); openid_indirect_error($request['openid.return_to'], 'Protocol Error: openid.return_to does not match realm.'); return; } } if (isset($request['openid.identity'])) { // Standard request log_debug('openid.identity found, use simpleid_checkid_identity'); $result = simpleid_checkid_identity($request, $immediate); } else { log_debug('openid.identity not found, trying extensions'); // Extension request $results = extension_invoke_all('checkid', $request, $immediate); // Filter out nulls $results = array_merge(array_diff($results, array(NULL))); // If there are still results, it is the lowest value, otherwise, it is CHECKID_PROTOCOL_ERROR $result = ($results) ? min($results) : CHECKID_PROTOCOL_ERROR; } switch ($result) { case CHECKID_APPROVAL_REQUIRED: log_info('CHECKID_APPROVAL_REQUIRED'); if ($immediate) { $response = simpleid_checkid_approval_required($request); simpleid_assertion_response($response, $request['openid.return_to']); } else { $response = simpleid_checkid_ok($request); simpleid_openid_consent_form($request, $response, $result); } break; case CHECKID_RETURN_TO_SUSPECT: log_info('CHECKID_RETURN_TO_SUSPECT'); if ($immediate) { $response = simpleid_checkid_error($request, $immediate); simpleid_assertion_response($response, $request['openid.return_to']); } else { $response = simpleid_checkid_ok($request); simpleid_openid_consent_form($request, $response, $result); } break; case CHECKID_OK: log_info('CHECKID_OK'); $response = simpleid_checkid_ok($request); $response = simpleid_sign($response, isset($request['openid.assoc_handle']) ? $request['openid.assoc_handle'] : NULL); simpleid_assertion_response($response, $request['openid.return_to']); break; case CHECKID_LOGIN_REQUIRED: log_info('CHECKID_LOGIN_REQUIRED'); if ($immediate) { $response = simpleid_checkid_login_required($request); simpleid_assertion_response($response, $request['openid.return_to']); } else { user_login_form('continue', pickle($request)); exit; } break; case CHECKID_IDENTITIES_NOT_MATCHING: case CHECKID_IDENTITY_NOT_EXIST: log_info('CHECKID_IDENTITIES_NOT_MATCHING | CHECKID_IDENTITY_NOT_EXIST'); $response = simpleid_checkid_error($request, $immediate); if ($immediate) { simpleid_assertion_response($response, $request['openid.return_to']); } else { simpleid_openid_consent_form($request, $response, $result); } break; case CHECKID_PROTOCOL_ERROR: if (isset($request['openid.return_to'])) { $response = simpleid_checkid_error($request, $immediate); simpleid_assertion_response($response, $request['openid.return_to']); } else { indirect_fatal_error('Unrecognised request.'); } break; } } /** * Processes a standard OpenID authentication request about an identity. * * Checks whether the current user logged into SimpleID matches the identity * supplied in an OpenID request. * * @param array &$request the OpenID request * @param bool $immediate whether checkid_immediate was used * @return int one of CHECKID_OK, CHECKID_APPROVAL_REQUIRED, CHECKID_RETURN_TO_SUSPECT, CHECKID_IDENTITY_NOT_EXIST, * CHECKID_IDENTITIES_NOT_MATCHING, CHECKID_LOGIN_REQUIRED or CHECKID_PROTOCOL_ERROR * @global array the current logged in user */ function simpleid_checkid_identity(&$request, $immediate) { global $user, $version; $realm = openid_get_realm($request, $version); // Check 1: Is the user logged into SimpleID as any user? if ($user == NULL) { return CHECKID_LOGIN_REQUIRED; } else { $uid = $user['uid']; } // Check 2: Is the user logged in as the same identity as the identity requested? // Choose the identity URL for the user automatically if ($request['openid.identity'] == OPENID_IDENTIFIER_SELECT) { $test_user = user_load($uid); $identity = $test_user['identity']; log_info('OpenID identifier selection: Selected ' . $uid . ' [' . $identity . ']'); } else { $identity = $request['openid.identity']; $test_user = user_load_from_identity($identity); } if ($test_user == NULL) return CHECKID_IDENTITY_NOT_EXIST; if ($test_user['uid'] != $user['uid']) { log_notice('Requested user ' . $test_user['uid'] . ' does not match logged in user ' . $user['uid']); return CHECKID_IDENTITIES_NOT_MATCHING; } // Pass the assertion to extensions $assertion_results = extension_invoke_all('checkid_identity', $request, $identity, $immediate); $assertion_results = array_merge(array_diff($assertion_results, array(NULL))); // Populate the request with the selected identity if ($request['openid.identity'] == OPENID_IDENTIFIER_SELECT) { $request['openid.claimed_id'] = $identity; $request['openid.identity'] = $identity; } // Check 3: Discover the realm and match its return_to $user_rp = (isset($user['rp'][$realm])) ? $user['rp'][$realm] : NULL; if (($version >= OPENID_VERSION_2) && SIMPLEID_VERIFY_RETURN_URL_USING_REALM) { $verified = FALSE; $rp_info = simpleid_get_rp_info($realm); $services = discovery_get_service_by_type($rp_info['services'], OPENID_RETURN_TO); log_info('OpenID 2 discovery: ' . count($services) . ' matching services'); if ($services) { $return_to_uris = array(); foreach ($services as $service) { $return_to_uris = array_merge($return_to_uris, $service['uri']); } foreach ($return_to_uris as $return_to) { if (openid_url_matches_realm($request['openid.return_to'], $return_to)) { log_info('OpenID 2 discovery: verified'); $verified = TRUE; break; } } } $rp_info['return_to_verified'] = $verified; simpleid_set_rp_info($realm, $rp_info); if (!$verified) { if (($user_rp != NULL) && ($user_rp['auto_release'] == 1)) { log_notice('OpenID 2 discovery: not verified, but overridden by user preference'); } else { log_notice('OpenID 2 discovery: not verified'); $assertion_results[] = CHECKID_RETURN_TO_SUSPECT; } } } // Check 4: For checkid_immediate, the user must already have given // permission to log in automatically. if (($user_rp != NULL) && ($user_rp['auto_release'] == 1)) { log_info('Automatic set for realm ' . $realm); $assertion_results[] = CHECKID_OK; return min($assertion_results); } else { $assertion_results[] = CHECKID_APPROVAL_REQUIRED; return min($assertion_results); } } /** * Obtains information on a relying party by performing discovery on them. Information * obtained includes the discovery URL, the parsed XRDS document, and any other * information saved by SimpleID extensions * * The results are cached for 1 hour. For performance reasons, stale results may * be obtained by using the $allow_stale parameter * * @param string $realm the openid.realm parameter * @param bool $allow_stale allow stale results to be returned, otherwise discovery * will occur * @return array containing information on a relying party. * @link http://openid.net/specs/openid-authentication-2_0.html#rp_discovery * @since 0.8 */ function simpleid_get_rp_info($realm, $allow_stale = FALSE) { $url = openid_realm_discovery_url($realm); log_info('simpleid_get_rp_info'); $rp_info = cache_get('rp-info', $realm); if (($rp_info == NULL) || (!isset($rp_info['updated'])) || (!$allow_stale && ($rp_info['updated'] < time() - 3600))) { log_info('OpenID 2 RP discovery: realm: ' . $realm . '; url: ' . $url); $rp_info = array( 'url' => $url, 'services' => discovery_get_services($url), 'updated' => time() ); cache_set('rp-info', $realm, $rp_info); } return $rp_info; } /** * Saves information on a relying party to disk. * * @param string $realm the openid.realm parameter * @param array $rp_info containing information on a relying party. * * @since 0.8 */ function simpleid_set_rp_info($realm, $rp_info) { if (!isset($rp_info['updated'])) $rp_info['updated'] = time(); cache_set('rp-info', $realm, $rp_info, $rp_info['updated']); } /** * Returns an OpenID response indicating a positive assertion. * * @param array $request the OpenID request * @return array an OpenID response with a positive assertion * @link http://openid.net/specs/openid-authentication-1_1.html#anchor17, http://openid.net/specs/openid-authentication-1_1.html#anchor23, http://openid.net/specs/openid-authentication-2_0.html#positive_assertions */ function simpleid_checkid_ok($request) { global $version; $message = array( 'openid.mode' => 'id_res', 'openid.op_endpoint' => simpleid_url(), 'openid.response_nonce' => openid_nonce() ); if (isset($request['openid.assoc_handle'])) $message['openid.assoc_handle'] = $request['openid.assoc_handle']; if (isset($request['openid.identity'])) $message['openid.identity'] = $request['openid.identity']; if (isset($request['openid.return_to'])) $message['openid.return_to'] = $request['openid.return_to']; if (($version >= OPENID_VERSION_2) && isset($request['openid.claimed_id'])) { $message['openid.claimed_id'] = $request['openid.claimed_id']; } $message = array_merge($message, extension_invoke_all('response', TRUE, $request)); log_info('OpenID authentication response: ' . log_array($message)); return openid_indirect_message($message, $version); } /** * Returns an OpenID response indicating a negative assertion to a * checkid_immediate request, where an approval of the relying party by the * user is required * * @param mixed $request the OpenID request * @return mixed an OpenID response with a negative assertion * @link http://openid.net/specs/openid-authentication-1_1.html#anchor17, http://openid.net/specs/openid-authentication-1_1.html#anchor23, http://openid.net/specs/openid-authentication-2_0.html#negative_assertions */ function simpleid_checkid_approval_required($request) { global $version; if ($version >= OPENID_VERSION_2) { $message = array('openid.mode' => 'setup_needed'); } else { $request['openid.mode'] = 'checkid_setup'; $message = array( 'openid.mode' => 'id_res', 'openid.user_setup_url' => simpleid_url('continue', 's=' . rawurlencode(pickle($request))) ); } $message = array_merge($message, extension_invoke_all('response', FALSE, $request)); log_info('OpenID authentication response: ' . log_array($message)); return openid_indirect_message($message, $version); } /** * Returns an OpenID response indicating a negative assertion to a * checkid_immediate request, where the user has not logged in. * * @param array $request the OpenID request * @return array an OpenID response with a negative assertion * @link http://openid.net/specs/openid-authentication-1_1.html#anchor17, http://openid.net/specs/openid-authentication-1_1.html#anchor23, http://openid.net/specs/openid-authentication-2_0.html#negative_assertions */ function simpleid_checkid_login_required($request) { global $version; if ($version >= OPENID_VERSION_2) { $message = array('openid.mode' => 'setup_needed'); } else { $message = array( 'openid.mode' => 'id_res', 'openid.user_setup_url' => simpleid_url('login', 'destination=continue&s=' . rawurlencode(pickle($request))) ); } $message = array_merge($message, extension_invoke_all('response', FALSE, $request)); log_info('OpenID authentication response: ' . log_array($message)); return openid_indirect_message($message, $version); } /** * Returns an OpenID response indicating a generic negative assertion. * * The content of the negative version depends on the OpenID version, and whether * the openid.mode of the request was checkid_immediate * * @param array $request the OpenID request * @param bool $immediate true if openid.mode of the request was checkid_immediate * @return array an OpenID response with a negative assertion * @link http://openid.net/specs/openid-authentication-1_1.html#anchor17, http://openid.net/specs/openid-authentication-1_1.html#anchor23, http://openid.net/specs/openid-authentication-2_0.html#negative_assertions */ function simpleid_checkid_error($request, $immediate = false) { global $version; $message = array(); if ($immediate) { if ($version >= OPENID_VERSION_2) { $message['openid.mode'] = 'setup_needed'; } else { $message['openid.mode'] = 'id_res'; } } else { $message['openid.mode'] = 'cancel'; } $message = array_merge($message, extension_invoke_all('response', FALSE, $request)); log_info('OpenID authentication response: ' . log_array($message)); return openid_indirect_message($message, $version); } /** * Signs an OpenID response, using signature information from an association * handle. * * @param array &$response the OpenID response * @param array $assoc_handle the association handle containing key information * for the signature. If $assoc_handle is not specified, a private association * is created * @return array the signed OpenID response * */ function simpleid_sign(&$response, $assoc_handle = NULL) { global $version; if (!$assoc_handle) { $assoc = _simpleid_create_association(ASSOCIATION_PRIVATE); $response['openid.assoc_handle'] = $assoc['assoc_handle']; } else { $assoc = cache_get('association', $assoc_handle); if ($assoc['created'] + SIMPLEID_ASSOC_EXPIRES_IN < time()) { // Association has expired, need to create a new one log_notice('Association handle ' . $assoc['assoc_handle'] . ' expired. Using stateless mode.'); $response['openid.invalidate_handle'] = $assoc_handle; $assoc = _simpleid_create_association(ASSOCIATION_PRIVATE); $response['openid.assoc_handle'] = $assoc['assoc_handle']; } } // If we are using stateless mode, then we need to cache the response_nonce // so that the RP can only verify once if (isset($assoc['private']) && ($assoc['private'] == 1) && isset($response['openid.response_nonce'])) { cache_set('stateless', $response['openid.response_nonce'], array( 'response_nonce' => $response['openid.response_nonce'], 'assoc_handle' => $response['openid.assoc_handle'])); } // Get all the signed fields [10.1] openid_parse_request($response); // Fill the namespace array $signed_fields = array('op_endpoint', 'return_to', 'response_nonce', 'assoc_handle', 'identity', 'claimed_id'); $signed_fields = array_merge($signed_fields, extension_invoke_all('signed_fields', $response)); // Check if the signed keys are actually present $to_sign = array(); foreach ($signed_fields as $field) { if (isset($response['openid.' . $field])) $to_sign[] = $field; } $response['openid.signed'] = implode(',', $to_sign); // Generate signature for this message $mac_key = $assoc['mac_key']; $assoc_types = openid_association_types(); $hmac_func = $assoc_types[$assoc['assoc_type']]['hmac_func']; $response['openid.sig'] = openid_sign($response, $to_sign, $mac_key, $hmac_func, $version); log_info('OpenID signed authentication response: ' . log_array($response)); return $response; } /** * Processes a direct verification request. This is used in the OpenID specification * to verify signatures generated using stateless mode. * * @param array $request the OpenID request * @see http://openid.net/specs/openid-authentication-1_1.html#mode_check_authentication, http://openid.net/specs/openid-authentication-2_0.html#verifying_signatures */ function simpleid_check_authentication($request) { global $version; log_info('OpenID direct verification: ' . log_array($request)); $is_valid = simpleid_verify_signatures($request); if ($is_valid) { $response = array('is_valid' => 'true'); } else { $response = array('is_valid' => 'false'); } // RP wants to check whether a handle is invalid if (isset($request['openid.invalidate_handle'])) { $invalid_assoc = cache_get('association', $request['openid.invalidate_handle']); if (!$invalid_assoc || ($invalid_assoc['created'] + SIMPLEID_ASSOC_EXPIRES_IN < time())) { // Yes, it's invalid $response['invalidate_handle'] = $request['openid.invalidate_handle']; } } log_info('OpenID direct verification response: ' . log_array($response)); openid_direct_response(openid_direct_message($response, $version)); } /** * Verifies the signature of a signed OpenID request/response. * * @param array $request the OpenID request/response * @return bool true if the signature is verified * @since 0.8 */ function simpleid_verify_signatures($request) { global $version; log_info('simpleid_verify_signatures'); $is_valid = TRUE; $assoc = (isset($request['openid.assoc_handle'])) ? cache_get('association', $request['openid.assoc_handle']) : NULL; $stateless = (isset($request['openid.response_nonce'])) ? cache_get('stateless', $request['openid.response_nonce']) : NULL; if (!$assoc) { log_notice('simpleid_verify_signatures: Association not found.'); $is_valid = FALSE; } elseif (!$assoc['assoc_type']) { log_error('simpleid_verify_signatures: Association does not contain valid assoc_type.'); $is_valid = FALSE; } elseif (!isset($assoc['private']) || ($assoc['private'] != 1)) { log_warn('simpleid_verify_signatures: Attempting to verify an association with a shared key.'); $is_valid = FALSE; } elseif (!$stateless || ($stateless['assoc_handle'] != $request['openid.assoc_handle'])) { log_warn('simpleid_verify_signatures: Attempting to verify a response_nonce more than once, or private association expired.'); $is_valid = FALSE; } else { $mac_key = $assoc['mac_key']; $assoc_types = openid_association_types(); $hmac_func = $assoc_types[$assoc['assoc_type']]['hmac_func']; $signed_keys = explode(',', $request['openid.signed']); $signature = openid_sign($request, $signed_keys, $mac_key, $hmac_func, $version); log_debug('***** Signature: ' . $signature); if ($signature != $request['openid.sig']) { log_warn('simpleid_verify_signatures: Signature supplied in request does not match the signatured generated.'); $is_valid = FALSE; } cache_delete('stateless', $request['openid.response_nonce']); } return $is_valid; } /** * Continues an OpenID authentication request. * * This function decodes an OpenID authentication request specified in the * s request parameter and feeds it to the * {@link simpleid_process_openid} function. This allows SimpleID to preserve * the state of an OpenID request. */ function simpleid_continue() { global $GETPOST; $request = unpickle($GETPOST['s']); openid_parse_request($request); simpleid_process_openid($request); } /** * Provides a form for user consent of an OpenID relying party, where the * {@link simpleid_checkid_identity()} function returns a CHECKID_APPROVAL_REQUIRED * or CHECKID_RETURN_TO_SUSPECT. * * Alternatively, provide a form for the user to rectify the situation where * {@link simpleid_checkid_identity()} function returns a CHECKID_IDENTITIES_NOT_MATCHING * or CHECKID_IDENTITY_NOT_EXIST * * @param array $request the original OpenID request * @param array $response the proposed OpenID response, subject to user * verification * @param int $reason either CHECKID_APPROVAL_REQUIRED, CHECKID_RETURN_TO_SUSPECT, * CHECKID_IDENTITIES_NOT_MATCHING or CHECKID_IDENTITY_NOT_EXIST */ function simpleid_openid_consent_form($request, $response, $reason = CHECKID_APPROVAL_REQUIRED) { global $user; global $xtpl; global $version; $request_state = pickle($request); user_header($request_state); $realm = openid_get_realm($request, $version); $xtpl->assign('token', get_form_token('rp')); $xtpl->assign('state', pickle($response)); $xtpl->assign('realm', htmlspecialchars($realm, ENT_QUOTES, 'UTF-8')); if ($response['openid.mode'] == 'cancel') { $xtpl->assign('switch_user_url', htmlspecialchars(simpleid_url('logout', 'destination=continue&s=' . rawurlencode($request_state), true))); $xtpl->assign('return_to', htmlspecialchars($request['openid.return_to'], ENT_QUOTES, 'UTF-8')); $xtpl->assign('identity', htmlspecialchars($request['openid.identity'], ENT_QUOTES, 'UTF-8')); $xtpl->parse('main.openid_consent.cancel'); } else { $xtpl->assign('javascript', ''); $rp = (isset($user['rp'][$realm])) ? $user['rp'][$realm] : NULL; $extensions = extension_invoke_all('consent_form', $request, $response, $rp); $xtpl->assign('extensions', implode($extensions)); if ($reason == CHECKID_RETURN_TO_SUSPECT) { $xtpl->parse('main.openid_consent.setup.suspect'); $xtpl->assign('realm_class', 'return-to-suspect'); } $xtpl->parse('main.openid_consent.setup'); } $xtpl->parse('main.openid_consent'); $xtpl->parse('main.framekiller'); header('X-Frame-Options: DENY'); $xtpl->assign('title', 'OpenID Login'); $xtpl->assign('page_class', 'dialog-page'); $xtpl->parse('main'); $xtpl->out('main'); } /** * Processes a user response from the {@link simpleid_openid_consent_form()} function. * * If the user verifies the relying party, an OpenID response will be sent to * the relying party. Otherwise, the dashboard will be displayed to the user. * */ function simpleid_openid_consent() { global $xtpl, $user, $version, $GETPOST; if ($user == NULL) { user_login_form(''); return; } if (!validate_form_token($GETPOST['tk'], 'rp')) { set_message('SimpleID detected a potential security attack. Please try again.'); $xtpl->assign('title', 'OpenID Login'); $xtpl->parse('main'); $xtpl->out('main'); return; } $uid = $user['uid']; $response = unpickle($GETPOST['s']); $version = openid_get_version($response); $return_to = $response['openid.return_to']; if (!$return_to) $return_to = $GETPOST['openid.return_to']; if ($GETPOST['op'] == 'Cancel') { $response = simpleid_checkid_error(false); if (!$return_to) set_message('Log in cancelled.'); } else { $now = time(); $realm = $GETPOST['openid.realm']; if (isset($user['rp'][$realm])) { $rp = $user['rp'][$realm]; } else { $rp = array('realm' => $realm, 'first_time' => $now); } $rp['last_time'] = $now; $rp['auto_release'] = (isset($GETPOST['autorelease']) && $GETPOST['autorelease']) ? 1 : 0; extension_invoke_all('consent', $GETPOST, $response, $rp); $user['rp'][$realm] = $rp; user_save($user); $response = simpleid_sign($response, isset($response['openid.assoc_handle']) ? $response['openid.assoc_handle'] : NULL); if (!$return_to) set_message('You were logged in successfully.'); } if ($return_to) { simpleid_assertion_response($response, $return_to); } else { page_dashboard(); } } /** * Sends an OpenID assertion response. * * The OpenID specification version 2.0 provides for the sending of assertions * via indirect communication. However, future versions of the OpenID * specification may provide for sending of assertions via direct communication. * * @param array $response the signed OpenID assertion response to send * @param string $indirect_url the URL to which the OpenID response is sent. If * this is an empty string, the response is sent via direct communication */ function simpleid_assertion_response($response, $indirect_url = NULL) { global $xtpl, $version; if ($indirect_url) { // We want to see if the extensions want to change the way indirect responses are made $results = extension_invoke_all('indirect_response', $indirect_url, $response); $results = array_filter($results, 'is_null'); $component = ($results) ? max($results) : OPENID_RESPONSE_QUERY; openid_indirect_response($indirect_url, $response, $component); } else { openid_direct_response(openid_direct_message($response, $version)); } } /** * Displays the XRDS document for this SimpleID installation. * */ function simpleid_xrds() { global $xtpl; log_debug('Providing XRDS.'); header('Content-Type: application/xrds+xml'); header('Content-Disposition: inline; filename=yadis.xml'); $types = extension_invoke_all('xrds_types'); foreach ($types as $type) { $xtpl->assign('uri', htmlspecialchars($type, ENT_QUOTES, 'UTF-8')); $xtpl->parse('xrds.op_xrds.type'); } $xtpl->assign('simpleid_base_url', htmlspecialchars(simpleid_url(), ENT_QUOTES, 'UTF-8')); $xtpl->parse('xrds.op_xrds'); $xtpl->parse('xrds'); $xtpl->out('xrds'); } ?> simpleid/www/common.inc0000644000175000017500000002604211710103700014737 0ustar danieldaniel * James Walker * * Copyright (C) Rowan Kerr and James Walker * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: common.inc 338 2010-11-20 01:52:38Z kmo $ */ /** * Common functions used by SimpleID, and the implementation of extensions. * * @package simpleid * @filesource */ /** * Sets a message to display to the user on the rendered SimpleID page. * * @param string $msg the message to set */ function set_message($msg) { global $xtpl; $xtpl->assign('message', $msg); $xtpl->parse('main.message'); } /** * Displays a fatal error message and exits. * * @param string $error the message to set */ function indirect_fatal_error($error) { global $xtpl; set_message($error); $xtpl->parse('main'); $xtpl->out('main'); exit; } /** * Determines whether the current connection with the user agent is via * HTTPS. * * HTTPS is detected if one of the following occurs: * * - $_SERVER['HTTPS'] is set to 'on' (Apache installations) * - $_SERVER['HTTP_X_FORWARDED_PROTO'] is set to 'https' (reverse proxies) * - $_SERVER['HTTP_FRONT_END_HTTPS'] is set to 'on' * * @return bool true if the connection is via HTTPS */ function is_https() { return (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on')) || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && (strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https')) || (isset($_SERVER['HTTP_FRONT_END_HTTPS']) && ($_SERVER['HTTP_FRONT_END_HTTPS'] == 'on')); } /** * Content type negotiation using the Accept Header. * * Under HTTP, the user agent is able to negoatiate the content type returned with * the server using HTTP Accept header. This header contains a comma-delimited * list of items (e.g. content types) which the user agent is able to * accept, ranked by a quality parameter. * * This function takes the header from the user agent, compares it against the * content types which the server can provide, then returns the item which the highest * quality which the server can provide. * * @param array $content_types an array of content types which the server can * provide * @param string $accept_header the header string provided by the user agent. * If NULL, this defaults to $_SERVER['HTTP_ACCEPT'] if available * @return string the negotiated content type, FALSE if $accept_header is NULL and * the user agent did not provide an Accept header, or NULL if the negotiation is * unsuccessful * * @since 0.8 * */ function negotiate_content_type($content_types, $accept_header = NULL) { $content_types = array_map("strtolower", $content_types); if (($accept_header == NULL) && isset($_SERVER['HTTP_ACCEPT'])) $accept_header = $_SERVER['HTTP_ACCEPT']; if ($accept_header) { $acceptible = preg_split('/\s*,\s*/', strtolower(trim($accept_header))); for ($i = 0; $i < count($acceptible); $i++) { $split = preg_split('/\s*;\s*q\s*=\s*/', $acceptible[$i], 2); $item = strtolower($split[0]); if (count($split) == 1) { $q = 1.0; } else { $q = doubleval($split[1]); } if ($q > 0.0) { if (in_array($item, $content_types)) { if ($q == 1.0) { return $item; } $candidates[$item] = $q; } else { $item = preg_quote($item, '/'); $item = strtr($item, array('\*' => '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+')); foreach ($content_types as $value) { if (preg_match("/^$item$/", $value)) { if ($q == 1.0) { return $value; } $candidates[$value] = $q; break; } } } } } if (isset($candidates)) { arsort($candidates); reset($candidates); return key($candidates); } return NULL; } else { // No headers return FALSE; } } /** * Serialises a variable for inclusion as a URL parameter. * * @param mixed $data the data to serialise * @return string serialised data * @see unpickle() */ function pickle($data) { return base64_encode(gzcompress(serialize($data))); } /** * Deserialises data specified in a URL parameter as a variable. * * @param string $pickle the serialised data * @return mixed the deserialised data * @see pickle() */ function unpickle($pickle) { return unserialize(gzuncompress(base64_decode($pickle))); } /** * Obtains the URI of the current request, given a base URI. * * @param string $base the base URI * @return string the request URI */ function get_request_uri($base) { $i = strpos($base, '//'); $i = strpos($base, '/', $i + 2); if ($i === false) { return $base . $_SERVER['REQUEST_URI']; } else { return substr($base, 0, $i) . $_SERVER['REQUEST_URI']; } } /** * Returns the base URL path, relative to the current host, of the SimpleID * installation. * * This is worked out from {@link SIMPLEID_BASE_URL}. It will always contain * a trailing slash. * * @return string the base URL path * @since 0.8 * @see SIMPLEID_BASE_URL */ function get_base_path() { static $base_path; if (!$base_path) { if ((substr(SIMPLEID_BASE_URL, -1) == '/') || (substr(SIMPLEID_BASE_URL, -9) == 'index.php')) { $url = SIMPLEID_BASE_URL; } else { $url = SIMPLEID_BASE_URL . '/'; } $parts = parse_url($url); $base_path = $parts['path']; } return $base_path; } /** * Obtains a SimpleID URL. URLs produced by SimpleID should use this function. * * @param string $q the q parameter * @param string $params a properly encoded query string * @param bool $relative whether a relative URL should be returns * @return string the url * * @since 0.7 */ function simpleid_url($q = '', $params = '', $relative = false) { if ($relative) { $url = get_base_path(); } else { // Make sure that the base has a trailing slash if ((substr(SIMPLEID_BASE_URL, -1) == '/') || (substr(SIMPLEID_BASE_URL, -9) == 'index.php')) { $url = SIMPLEID_BASE_URL; } else { $url = SIMPLEID_BASE_URL . '/'; } } if (SIMPLEID_CLEAN_URL) { $url .= $q . (($params == '') ? '' : '?' . $params); } elseif (($q == '') && ($params == '')) { $url .= ''; } else { $url .= 'index.php?q=' . $q . (($params == '') ? '' : '&' . $params); } return $url; } /** * Obtains a form token given a form ID. * * Form tokens are used in SimpleID forms to guard against cross-site forgery * attacks. * * @param string $id the form ID * @return string a form token */ function get_form_token($id) { global $user; if (store_get('site-token') == NULL) { $site_token = mt_rand(); store_set('site-token', $site_token); } else { $site_token = store_get('site-token'); } if ($user == NULL) { return md5($id . $site_token); } else { return md5(session_id() . $id . $site_token); } } /** * Checks whether a form token is valid * * @param string $token the token returned by the user agent * @param string $id the form ID * @return bool true if the form token is valid */ function validate_form_token($token, $id) { global $user; $site_token = store_get('site-token'); if ($user == NULL) { return ($token == md5($id . $site_token)); } else { return ($token == md5(session_id() . $id . $site_token)); } } /* ------- SimpleID extension support ---------------------------------------- */ /** * This variable holds an array of extensions specified by the user * * @global array $simpleid_extensions * @see SIMPLEID_EXTENSIONS */ $simpleid_extensions = array(); /** * Initialises the extension mechanism. This function looks up the extensions * to load in the {@link SIMPLEID_EXTENSIONS} constants, loads them, then * calls the ns hook. */ function extension_init() { global $simpleid_extensions; $simpleid_extensions = preg_split('/,\s*/', SIMPLEID_EXTENSIONS); foreach ($simpleid_extensions as $extension) { include_once 'extensions/' . $extension . '/' . $extension . '.extension.inc'; } } /** * Invokes a hook in all the loaded extensions. * * @param string $function the name of the hook to call * @param mixed $args the arguments to the hook * @return array the return values from the hook */ function extension_invoke_all() { global $simpleid_extensions; $args = func_get_args(); $function = array_shift($args); $return = array(); foreach ($simpleid_extensions as $extension) { if (function_exists($extension . '_' . $function)) { log_debug('extension_invoke_all: ' . $extension . '_' . $function); $result = call_user_func_array($extension . '_' . $function, $args); if (isset($result) && is_array($result)) { $return = array_merge($return, $result); } elseif (isset($result)) { $return[] = $result; } } } return $return; } /** * Invokes a hook in a specified extension. * * @param string $extension the extension to call * @param string $function the name of the hook to call * @param mixed $args the arguments to the hook * @return mixed the return value from the hook */ function extension_invoke() { $args = func_get_args(); $extension = array_shift($args); $function = array_shift($args); if (function_exists($extension . '_' . $function)) { log_debug('extension_invoke: ' . $extension . '_' . $function); return call_user_func_array($extension . '_' . $function, $args); } } /** * Returns an array of currently loaded extensions. * * @param array a list of the names of the currently loaded extensions. */ function get_extensions() { global $simpleid_extensions; return $simpleid_extensions; } ?> simpleid/www/filesystem.store.inc0000644000175000017500000002135611710103700016771 0ustar danieldanielmust return false. * * The credentials are supplied as an array using the $credentials parameter. * Typically this array will be a subset of the $_POST superglobal passed to the * {@link user_login()} function. Thus it will generally contain the keys 'pass' and * 'digest'. * * This function must check whether the credentials supplied matches the credentials * for the specified user in the store. If for any reason that credentials * do not match, this function must return false. * * @param string $uid the name of the user to verify * @param array $credentials the credentials supplied by the browser * @param bool $allow_legacy_login true to verify using a plaintext password instead of * digest * @return bool whether the credentials supplied matches those for the specified * user */ function store_user_verify_credentials($uid, $credentials, $allow_legacy_login = FALSE) { $test_user = user_load($uid); if ($test_user == NULL) return false; if ($credentials['digest'] && !_user_verify_digest($credentials['digest'], $credentials['nonce'], $test_user)) { return false; } elseif ($allow_legacy_login && !$credentials['digest'] && (md5($credentials['pass']) != $test_user['pass'])) { return false; } return true; } /** * Finds the user name from a specified OpenID Identity URI. * * @param string $identity the Identity URI of the user to load * @return string the user name for the Identity URI, or NULL if no user has * the specified Identity URI */ function store_get_uid($identity) { $uid = cache_get('identity', $identity); if ($uid !== NULL) return $uid; $r = NULL; $dir = opendir(SIMPLEID_IDENTITIES_DIR); while (($file = readdir($dir)) !== false) { $filename = SIMPLEID_IDENTITIES_DIR . '/' . $file; if ((filetype($filename) != "file") || (!preg_match('/^(.+)\.identity$/', $file, $matches))) continue; $uid = $matches[1]; $test_user = store_user_load($uid); cache_set('identity', $test_user['identity'], $uid); if ($test_user['identity'] == $identity) { $r = $uid; } } closedir($dir); return $r; } /** * Saves user data for a specific user name. * * This data is stored in the user store file. * * @param string $uid the name of the user * @param array $data the data to save * @param array $exclude an array of keys to exclude from the user store file. * These are generally keys which are stored in the identity file. * * @since 0.7 */ function store_user_save($uid, $data, $exclude = array()) { foreach ($exclude as $key) { if (isset($data[$key])) unset($data[$key]); } if (!_store_is_valid_name($uid)) { trigger_error("Invalid user name for filesystem store", E_USER_ERROR); return; } $store_file = SIMPLEID_STORE_DIR . "/$uid.usrstore"; $file = fopen($store_file, 'w'); fwrite($file, serialize($data)); fclose($file); } /** * Loads an application setting. * * @param string $name the name of the setting to return * @param mixed $default the default value to use if this variable has never been set * @return mixed the value of the setting * */ function store_get($name, $default = NULL) { global $simpleid_settings; if (!_store_is_valid_name($name)) return $default; if (!isset($simpleid_settings[$name])) { $setting_file = SIMPLEID_STORE_DIR . "/$name.setting"; if (file_exists($setting_file)) { $simpleid_settings[$name] = unserialize(file_get_contents($setting_file)); } else { return $default; } } return $simpleid_settings[$name]; } /** * Saves an application setting. * * @param string $name the name of the setting to save * @param mixed $value the value of the setting * */ function store_set($name, $value) { global $simpleid_settings; if (!_store_is_valid_name($name)) { trigger_error("Invalid setting name for filesystem store", E_USER_ERROR); return; } $simpleid_settings[$name] = $value; $setting_file = SIMPLEID_STORE_DIR . "/$name.setting"; $file = fopen($setting_file, 'w'); fwrite($file, serialize($value)); fclose($file); } /** * Deletes an application setting. * * @param string $name the name of the setting to delete * */ function store_del($name) { global $simpleid_settings; if (!_store_is_valid_name($name)) { trigger_error("Invalid setting name for filesystem store", E_USER_ERROR); return; } if (isset($simpleid_settings[$name])) unset($simpleid_settings[$name]); $setting_file = SIMPLEID_STORE_DIR . "/$name.setting"; if (file_exists($setting_file)) unlink($setting_file); } /** * Determines whether a name is a valid name for use with this store. * * For file system storage, a name is not valid if it contains either a * directory separator (i.e. / or \). * * @param string $name the name to check * @return boolean whether the name is valid for use with this store * */ function _store_is_valid_name($name) { return preg_match('!\A[^/\\\\]*\z!', $name); } ?> simpleid/www/config.default.inc0000644000175000017500000000370611710103700016341 0ustar danieldaniel * James Walker * * Copyright (C) Rowan Kerr and James Walker * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: config.default.inc 332 2010-10-31 02:58:39Z kmo $ */ /** * Default configuration settings * * @package simpleid * @filesource */ /** * Define a constant if it has not been defined already. * * @param $name string the name of the constant * @param $value mixed the value of the constant - only scalar and null values * are allowed */ function define_default($name, $value) { if (!defined($name)) { define($name, $value); } } define_default('SIMPLEID_CLEAN_URL', false); define_default('SIMPLEID_ALLOW_LEGACY_LOGIN', false); define_default('SIMPLEID_ALLOW_AUTOCOMPLETE', false); define_default('SIMPLEID_EXTENSIONS', 'sreg'); define_default('SIMPLEID_VERIFY_RETURN_URL_USING_REALM', true); define_default('SIMPLEID_STORE', 'filesystem'); define_default('SIMPLEID_STORE_DIR', SIMPLEID_CACHE_DIR); define_default('SIMPLEID_LOGFILE', ''); define_default('SIMPLEID_LOGLEVEL', 4); if (function_exists('date_default_timezone_set')) date_default_timezone_set(@date_default_timezone_get()); ?> simpleid/www/cache.inc0000644000175000017500000001117711710103700014515 0ustar danieldaniel * James Walker * * Copyright (C) Rowan Kerr and James Walker * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: cache.inc 216 2009-10-29 12:04:47Z kmo $ */ /** * Functions for caching and persistence. * * @package simpleid * @filesource */ /** * Stores data into the cache. * * @param string $type the type of data in the cache * @param string $key an identifier * @param mixed $data the data to store * @param int $time if present, sets the modification time of the cache file to this * time */ function cache_set($type, $key, $data, $time = NULL) { $filename = _cache_get_name($type, $key); $file = fopen($filename, 'w'); fwrite($file, serialize($data)); fclose($file); if ($time != NULL) { touch($filename, $time); } } /** * Obtains data from the cache. * * @param string $type the type of data in the cache * @param string $key an identifier * @return mixed the data associated with the type and key, or NULL if the cache * does not contain the requested data. */ function cache_get($type, $key) { $filename = _cache_get_name($type, $key); if (!file_exists($filename)) return NULL; return unserialize(file_get_contents($filename)); } /** * Obtains all data of a particular type from the cache. * * @param string $type the type of data in the cache * @return mixed an array of data associated with the type, or NULL if the cache * does not contain the requested data. */ function cache_get_all($type) { $r = array(); $dir = opendir(CACHE_DIR); while (($file = readdir($dir)) !== false) { $filename = CACHE_DIR . '/' . $file; if ((filetype($filename) != "file") || (strpos($file, $type . '-') !== 0)) continue; $r[] = unserialize(file_get_contents($filename)); } closedir($dir); return $r; } /** * Deletes data from the cache. * * @param string $type the type of data in the cache * @param string $key an identifier */ function cache_delete($type, $key) { $filename = _cache_get_name($type, $key); if (file_exists($filename)) unlink($filename); } /** * Garbage collects data stored the cache. Data is deleted if it was stored * for longer than the specified expiry * * @param int $expiry the expiry time, in seconds, after which data will be deleted * @param string $type the type of data in the cache */ function cache_gc($expiry, $type = NULL) { $dir = opendir(CACHE_DIR); while (($file = readdir($dir)) !== false) { $filename = CACHE_DIR . '/' . $file; if (($type != NULL) && (strpos($file, $type . '-') !== 0)) continue; if ((filetype($filename) == "file") && (filectime($filename) < time() - $expiry)) { unlink($filename); } } closedir($dir); } /** * Returns the time remaining, in seconds, before the data associated with the * type and key become subject to garbage collection by {@link cache_gc()}. * * @param string $type the type of data in the cache * @param string $key an identifier * @param int $expiry the expiry time, in seconds, which would be passed onto the * {@link cache_gc()} function * @return int the time remaining before expiry, rounded downwards, * or zero if the cache does not contain the requested data * @since 0.8 */ function cache_ttl($type, $key, $expiry) { $filename = _cache_get_name($type, $key); if (!file_exists($filename)) return 0; return filectime($filename) - (time() - $expiry) - 1; } /** * Returns the name of the cache data file, given a type and an identifier. * * @param string $type the type of data in the cache * @param string $key an identifier * @return string a file name */ function _cache_get_name($type, $key) { return CACHE_DIR . '/' . $type . '-' . md5($key) . '.cache'; } ?> simpleid/www/bignum.inc0000644000175000017500000001274211710103700014732 0ustar danieldaniel 0) { array_unshift($bytes, bignum_mod($num, 256)); $num = bignum_div($num, 256); } if ($bytes && ($bytes[0] > 127)) { array_unshift($bytes, 0); } $byte_stream = ''; foreach ($bytes as $byte) { $byte_stream .= pack('C', $byte); } return $byte_stream; } return FALSE; } /** * Adds two bignums * * @param resource $a * @param resource $b * @return resource a bignum representing a + b */ function bignum_add($a, $b) { if (BIGNUM_GMP) { return gmp_add($a, $b); } else { return bcadd($a, $b); } } /** * Multiplies two bignums * * @param resource $a * @param resource $b * @return resource a bignum representing a * b */ function bignum_mul($a, $b) { if (BIGNUM_GMP) { return gmp_mul($a, $b); } else { return bcmul($a, $b); } } /** * Divides two bignums * * @param resource $a * @param resource $b * @return resource a bignum representing a / b */ function bignum_div($a, $b) { if (BIGNUM_GMP) { return gmp_div($a, $b); } else { return bcdiv($a, $b); } } /** * Raise base to power exp * * @param resource $base the base * @param mixed $exp the exponent, as an integer or a bignum * @return resource a bignum representing base ^ exp */ function bignum_pow($base, $exp) { if (BIGNUM_GMP) { if (is_resource($exp) && (get_resource_type($exp) == 'gmp')) $exp = gmp_intval($exp); return gmp_pow($base, $exp); } else { return bcpow($base, $exp); } } /** * Returns n modulo d * * @param resource $n * @param resource $d * @return resource a bignum representing n mod d */ function bignum_mod($n, $d) { if (BIGNUM_GMP) { return gmp_mod($n, $d); } else { return bcmod($n, $d); } } /** * Raise a number into power with modulo * * @param resource $base the base * @param resource $exp the exponent * @param resource $mod the modulo * @return resource a bignum representing base ^ exp mod mod */ function bignum_powmod($base, $exp, $mod) { if (BIGNUM_GMP) { return gmp_powm($base, $exp, $mod); } elseif (function_exists('bcpowmod')) { return bcpowmod($base, $exp, $mod); } else { $square = bignum_mod($base, $mod); $result = 1; while (bignum_cmp($exp, 0) > 0) { if (bignum_mod($exp, 2)) { $result = bignum_mod(bignum_mul($result, $square), $mod); } $square = bignum_mod(bignum_mul($square, $square), $mod); $exp = bignum_div($exp, 2); } return $result; } } /** * Compares two bignum * * @param resource $a * @param resource $b * @return int positive value if a > b, zero if a = b and a negative value if a < b */ function bignum_cmp($a, $b) { if (BIGNUM_GMP) { return gmp_cmp($a, $b); } else { return bccomp($a, $b); } } ?> simpleid/www/simpleweb.inc0000644000175000017500000001063011710103700015432 0ustar danieldanielroute array. The route array is an array that maps * URLs (called patterns) to PHP functions or methods (called routes). * * Patterns are regular expressions, which are tested against the URL one at a time. * Subpatterns (i.e. patterns within parentheses) are then passed on as arguments * to the route. * * Routes are either functions, static methods or object methods. A function is * denoted by the function name. A static method is denoted by the class name, * followed by :: then the method name. An object method is denoted by the class * name, followed by -> then the method name. An instance of the class will be * created before an object method is called. * * An example of a routes array is given below: * * * 'function1', * 'b/(.+)' => 'function2', // arguments * 'c' => 'ClassA::method', // static method * 'd' => 'ClassB->method', // object method * ); * ?> * * * Once the route array is populated, the {@link simpleweb_run()} function * is then called to handle the URL. * * @package simpleweb * @since 0.7 */ /** * Handles a supplied request, based on a set of routes. * * @param array $routes the routes array, as described in {@link simpleweb.inc this page} * @param string $request_path the request path against which the routes are applied. If * NULL, then the request URI supplied by the web server will be used. * @param string $not_found_route the default route if none of the patterns match. If * NULL, then an HTTP 404 error is raised * @return mixed the result from calling the route. * */ function simpleweb_run($routes, $request_path = NULL, $not_found_route = NULL) { if ($request_path == NULL) { // We take the request path from the request URI $request_path = $_SERVER['REQUEST_URI']; // Strip off all parts to the script file name $script_name = basename($_SERVER['SCRIPT_NAME']); $request_path = substr($request_path, strpos($request_path, $script_name) + strlen($script_name)); $request_path = trim($request_path, '/'); } foreach ($routes as $pattern => $route) { if (!isset($route)) continue; $regex = '#^' . trim($pattern, '/') . '$#i'; if (!preg_match($regex, $request_path, $args) > 0) continue; $args = (count($args) > 1) ? array_slice($args, 1) : array(); return _simpleweb_invoke($route, $args); } if ($not_found_route) return _simpleweb_invoke($not_found_route, array($request_path)); return _simpleweb_not_found(); } /** * Invokes a route. * * @param string $route the route * @param array $args the arguments * @return mixed the result from calling the route. */ function _simpleweb_invoke($route, $args = array()) { if (strpos($route, '::') !== false) { list($class, $method) = split($route, '::', 2); return call_user_func_array(array($class, $method), $args); } elseif(strpos($route, '->') !== false) { list($class, $method) = split($route, '->', 2); $object &= new $class; return call_user_func_array(array($object, $method), $args); } else { return call_user_func_array($route, $args); } } /** * Displays a HTTP 404 Not Found error and exits. */ function _simpleweb_not_found() { header('Status: 404'); header('Content-Type: text/plain'); print 'Not Found'; exit; } ?> simpleid/www/random.inc0000644000175000017500000000647311710103700014735 0ustar danieldaniel simpleid/www/http.inc0000644000175000017500000003021111710103700014417 0ustar danieldaniel value pairs * @param string $method the HTTP request method * @param int $retry the maximum number of redirects allowed * @return array containing keys 'error-code' (for communication errors), 'error' * (for communication errors), 'data' (content returned), 'code' (the HTTP status code), 'http-error' * (if the HTTP status code is not 200 or 304), 'protocol' (the HTTP protocol in the response), * 'headers' (an array of return headers in lowercase), * 'content-type' (the HTTP content-type returned) */ function http_make_request($url, $headers = array(), $method = 'GET', $retry = 3) { // If CURL is available, we use it if (extension_loaded('curl')) { $response = _http_make_request_curl($url, $headers, $method, $retry); } else { $response = _http_make_request_fsock($url, $headers, $method, $retry); } if (!isset($response['error-code'])) { $valid_codes = array( 100, 101, 200, 201, 202, 203, 204, 205, 206, 300, 301, 302, 303, 304, 305, 307, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 500, 501, 502, 503, 504, 505 ); // RFC 2616 states that all unknown HTTP codes must be treated the same as the // base code in their class. if (!in_array($response['code'], $valid_codes)) { $response['code'] = floor($response['code'] / 100) * 100; } if (($response['code'] != 200) && ($response['code'] != 304)) { $response['http-error'] = $response['code']; } } return $response; } /** * Returns the protocols currently supported for making remote requests. * * If libcurl is used, this function returns a list of protocols supported by the * included build of the library. If libcurl is not used, then HTTP is the * only protocol supported. * * @return array an array of protocols */ function http_protocols() { if (extension_loaded('curl')) { $curl_version = curl_version(); return $curl_version['protocols']; } else { return array('http'); } } /** * Performs an HTTP request using libcurl. * * @param string $url the URL * @param array $headers HTTP headers containing name => value pairs * @param string $method the HTTP request method * @param int $retry the maximum number of redirects allowed * @return array containing keys 'error-code' (for communication errors), 'error' * (for communication errors), 'data' (content returned), 'code' (the HTTP status code), 'http-error' * (if the HTTP status code is not 200 or 304), 'headers' (an array of return headers), * 'content-type' (the HTTP content-type returned) */ function _http_make_request_curl($url, $headers = array(), $method = 'GET', $retry = 3) { // CURLOPT_FOLLOWLOCATION only works when safe mode is off or when open_basedir is set // In these instances we will need to follow redirects manually $manual_redirect = ((@ini_get('safe_mode') === 1) // safe mode || (strtolower(@ini_get('safe_mode')) == 'on') // safe mode || (@ini_get('open_basedir') != false)); // open_basedir $version = curl_version(); $curl = curl_init($url); if (version_compare($version['version'], '7.10.5', '>=')) { curl_setopt($curl, CURLOPT_ENCODING, ''); } if (!$manual_redirect) curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($curl, CURLOPT_MAXREDIRS, $retry); curl_setopt($curl, CURLOPT_HTTPHEADER, array(implode("\n", $headers) . "\n")); curl_setopt($curl, CURLOPT_USERAGENT, SIMPLEHTTP_USER_AGENT); curl_setopt($curl, CURLOPT_TIMEOUT, 20); curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 20); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HEADER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); $response = curl_exec($curl); if (($response === FALSE) && ((curl_errno($curl) == 23) || (curl_errno($curl) == 61))) { curl_setopt($curl, CURLOPT_ENCODING, 'none'); $response = curl_exec($curl); } if ($response === FALSE) { $result = array(); $result['error-code'] = curl_errno($curl); $result['error'] = curl_error($curl); } else { $result['code'] = curl_getinfo($curl, CURLINFO_HTTP_CODE); $result['url'] = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL); $result['content-type'] = curl_getinfo($curl, CURLINFO_CONTENT_TYPE); // Parse response. $result['raw'] = $response; $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); $result['data'] = substr($response, $header_size); $response_headers = substr($response, 0, $header_size - 4); // In case where redirect occurs, we want the last set of headers $header_blocks = explode("\r\n\r\n", $response_headers); $header_block = array_pop($header_blocks); $result = array_merge($result, _http_parse_headers($header_block, TRUE)); // If we are in safe mode, we need to process redirects manually if ($manual_redirect && (($result['code'] == 301) || ($result['code'] == 302) || ($result['code'] == 307))) { if ($retry == 0) { // Too many times, return an error $result['error-code'] = 47; $result['error'] = 'Too many redirects'; } else { curl_close($curl); return _http_make_request_curl($result['headers']['location'], $headers, $method, $retry - 1); } } } curl_close($curl); return $result; } /** * Performs an HTTP request using sockets. * * @param string $url the URL * @param array $headers HTTP headers containing name => value pairs * @param string $method the HTTP request method * @param int $retry the maximum number of redirects allowed * @return array containing keys 'error-code' (for communication errors), 'error' * (for communication errors), 'data' (content returned), 'code' (the HTTP status code), 'http-error' * (if the HTTP status code is not 200 or 304), 'headers' (an array of return headers), * 'content-type' (the HTTP content-type returned) */ function _http_make_request_fsock($url, $headers = array(), $method = 'GET', $retry = 3) { $result = array(); $parts = parse_url($url); if (!isset($parts)) { $result['error-code'] = 3; $result['error'] = 'URL not properly formatted'; return $result; } if ($parts['scheme'] == 'http') { $port = isset($parts['port']) ? $parts['port'] : 80; $host = $parts['host']; } elseif ($parts['scheme'] == 'https') { $port = isset($parts['port']) ? $parts['port'] : 443; $host = 'ssl://' . $uri['host']; } else { $result['error-code'] = 1; $result['error'] = 'Unsupported protocol'; } $fp = @fsockopen($host, $port, $errno, $errstr, 15); if (!$fp) { $result['error-code'] = 7; $result['error'] = "Cannot connect: Error $errno:" . trim($errstr); return $result; } if (isset($parts['path'])) { $path = $url_parts['path']; if (isset($parts['query'])) $path .= '?' . $url_parts['query']; } else { $path = '/'; } $headers = array_merge( array( 'Host' => $parts['host'], 'User-Agent' => SIMPLEHTTP_USER_AGENT, 'Connection' => 'close' ), $headers ); if (isset($parts['user']) && isset($parts['pass'])) { $headers['Authorization'] = 'Basic '. base64_encode($uri['user'] . (!empty($uri['pass']) ? ":". $uri['pass'] : '')); } $request = $method . ' '. $path ." HTTP/1.0\r\n"; $keys = array_keys($headers); for ($i = 0; $i < count($keys); $i++) { $request .= $keys[$i] . ': ' . $headers[$keys[$i]] . "\r\n"; } // End of headers - separator $request .= "\r\n"; fwrite($fp, $request); // Fetch response. $response = ''; while (!feof($fp) && $chunk = fread($fp, 1024)) { $response .= $chunk; } fclose($fp); // Parse response. list($header_block, $result['data']) = explode("\r\n\r\n", $response, 2); $result = array_merge($result, _http_parse_headers($header_block, FALSE)); // Process redirects if (($result['code'] == 301) || ($result['code'] == 302) || ($result['code'] == 307)) { if ($retry == 0) { // Too many times, return an error $result['error-code'] = 47; $result['error'] = 'Too many redirects'; } else { $result = _http_make_request_fsock($result['headers']['location'], $headers, $method, $retry - 1); } } $result['url'] = $url; return $result; } /** * Parses HTTP response headers. * * @param string $header_block the unparsed header block * @param bool $curl if true, use simplified parsing as libcurl already parses * the headers * @return an array containing the following keys: 'protocol' (the HTTP protocol in the response), * 'headers' (an array of return headers in lowercase). If $curl is false, additional * parsing is done for 'code' and 'content-type' */ function _http_parse_headers($header_block, $curl) { $headers = array(); $result = array(); // Split the status line from the rest of the message header list($status, $header_block) = preg_split("/\r\n|\n|\r/", $header_block, 2); // RFC 2616, section 4.2: Header fields can be extended over multiple lines // by preceding each extra line with at least one space or tab. So we need // to join them... $header_block = preg_replace('/(\r\n|\n|\r)( |\t)+/', '', $header_block); // Then split them to get the fields $fields = preg_split("/\r\n|\n|\r/", $header_block); // Parse the status line list($protocol, $code, $reason) = explode(' ', trim($status), 3); $result['protocol'] = $protocol; if (!$curl) $result['code'] = $code; // Parse headers. while ($field = trim(array_shift($fields))) { list($header, $value) = explode(':', $field, 2); // Headers are case insensitive $header = strtolower($header); if (isset($headers[$header])) { // RFC 2616, section 4.2: Multiple headers with the same field // name is the same as a concatenating all the headers in a single // header, separated by commas. $headers[$header] .= ','. trim($value); } else { $headers[$header] = trim($value); } if (!$curl && (strtolower($header) == 'content-type')) $result['content-type'] = $value; } $result['headers'] = $headers; return $result; } ?> simpleid/www/log.inc0000644000175000017500000001120211710103700014220 0ustar danieldaniel 'DEBUG', SIMPLEID_LOG_INFO => 'INFO', SIMPLEID_LOG_NOTICE => 'NOTICE', SIMPLEID_LOG_WARN => 'WARN', SIMPLEID_LOG_ERROR => 'ERROR', SIMPLEID_LOG_FATAL => 'FATAL' ); } /* If a priority hasn't been specified, use the default value. */ if ($level === false) { $level = SIMPLEID_LOG_INFO; } /* Abort early if the priority is above the maximum logging level. */ if ($level > SIMPLEID_LOGLEVEL) { return false; } /* If the log file isn't already open, open it now. */ if (($log == NULL) && !log_open()) { return false; } /* Build the string containing the complete log line. */ $line = sprintf('%1$s %2$s [%3$s] %4$s', strftime(SIMPLEID_DATE_TIME_FORMAT), session_id(), $levels[$level], $message) . "\n"; /* Write the log line to the log file. */ $success = (fwrite($log, $line) !== false); return $success; } ?> simpleid/UPGRADE.txt0000644000175000017500000000760011710103700013757 0ustar danieldaniel// $Id: UPGRADE.txt 349 2010-12-19 00:15:12Z kmo $ Upgrading SimpleID ================== Introduction ------------ SimpleID is currently in heavy development, with the software changing rapidly. As a result, it is very important to upgrade SimpleID when a new version is released. General information on upgrading can be found at . This document sets out the additional steps which may need to be performed to upgrade to a specific version of SimpleID. Upgrading to SimpleID 0.8 ------------------------- SimpleID 0.8 does not require any additional steps as part of the upgrade process. However, you will still need to run the upgrade script to complete the upgrade. To run the script, use your web browser to go to http://www.exmaple.com/simpleid/upgrade.php where http://www.exmaple.com/simpleid/ is the URL of your SimpleID server (where you have moved the www directory). You will need to be logged in as an administrator to proceed with the script. Upgrading to SimpleID 0.7 ------------------------- 1. New storage framework SimpleID introduced a new storage framework. The new framework allows SimpleID to store additional information about your identity. As a result, you will need to be aware that there is a new configuration option called SIMPLEID_STORE_DIR, which specifies the directory where this information will be stored. This directory must exist and be readable and writable by the web server. If you are upgrading from SimpleID 0.6, this setting will default to the directory specified by SIMPLEID_CACHE_DIR in your config.inc. However, it is a good idea to place this in a separate directory. To do this, add the following line to your config.inc: define('SIMPLEID_STORE_DIR', ''); 2. Administrators SimpleID 0.7 introduced the concept of administrators. Administrators have access to certain functions which regular users cannot. To make a user an administrator, edit the user's identity file to include the following line: administrator=1 3. User Interface Extension SimpleID 0.7 introduced support for the draft OpenID User Interface Extension. It is enabled by default for new installations of SimpleID, however if you are upgrading you may need to enable it manually. To do so, edit your config.inc to change the SIMPLEID_EXTENSIONS configuration option to include ui. For example: define('SIMPLEID_EXTENSIONS', 'sreg,ui'); 4. Upgrade script SimpleID introduced a new upgrade script. This means that whenever you upgrade you will also need to run the script. To run the script, use your web browser to go to http://www.exmaple.com/simpleid/upgrade.php where http://www.exmaple.com/simpleid/ is the URL of your SimpleID server (where you have moved the www directory). You will need to be logged in as an administrator to proceed with the script. Upgrading to SimpleID 0.6 ------------------------- SimpleID version 0.6 introduced a new log in system. The new system allows you to log in to SimpleID without sending your password in plain text. Your password is used to create a cryptographic digest, which is then sent to the SimpleID server and verified. As a result, you need to be aware of two things: 1. You browser must have JavaScript switched on in order to use the new log in system. If JavaScript is not switched on, SimpleID reverts to the "legacy" log in system used in previous versions, subject to the important point below. 2. By default, SimpleID version 0.6 will not accept logins under the legacy system. You can override this by putting the following line in your config.inc: define('SIMPLEID_ALLOW_LEGACY_LOGIN', true); It is STRONGLY RECOMMENDED that you DO NOT switch the legacy login system on, as it is substantially less secure than the new login system. Use this ONLY if your browser does not support JavaScript. simpleid/build.properties0000644000175000017500000002106211710103700015342 0ustar danieldaniel#Ant properties #Thu Jan 26 09:51:22 EST 2012 ant.core.lib=C\:\\Program Files (x86)\\ant\\lib\\ant.jar ant.file=C\:\\Users\\Kelvin Mo\\Documents\\Programming\\simpleid\\build.xml ant.file.type=file ant.home=C\:\\Program Files (x86)\\ant ant.java.version=1.6 ant.library.dir=C\:\\Program Files (x86)\\ant\\lib ant.project.default-target=dist ant.project.invoked-targets=sourceforge-release ant.version=Apache Ant(TM) version 1.8.2 compiled on December 20 2010 awt.toolkit=sun.awt.windows.WToolkit basedir=C\:\\Users\\Kelvin Mo\\Documents\\Programming\\simpleid build.properties.file=simpleid-release/build.properties build.version=0.8.1 dist.dir=..\\dist env.\=\:\:=\:\:\\ env.\=C\:=C\:\\Users\\Kelvin Mo\\Documents\\Programming\\simpleid env.ALLUSERSPROFILE=C\:\\ProgramData env.AMDAPPSDKROOT=C\:\\Program Files (x86)\\AMD APP\\ env.APPDATA=C\:\\Users\\Kelvin Mo\\AppData\\Roaming env.CLASSPATH=.;C\:\\Program Files (x86)\\Java\\jre6\\lib\\ext\\QTJava.zip env.COMPUTERNAME=BLAXLAND3 env.ComSpec=C\:\\Windows\\system32\\cmd.exe env.CommonProgramFiles=C\:\\Program Files (x86)\\Common Files env.CommonProgramFiles(x86)=C\:\\Program Files (x86)\\Common Files env.CommonProgramW6432=C\:\\Program Files\\Common Files env.FP_NO_HOST_CHECK=NO env.HOMEDRIVE=C\: env.HOMEPATH=\\Users\\Kelvin Mo env.LOCALAPPDATA=C\:\\Users\\Kelvin Mo\\AppData\\Local env.LOGONSERVER=\\\\BLAXLAND3 env.NUMBER_OF_PROCESSORS=8 env.OS=Windows_NT env.PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC env.PHPRC=C\:\\Program Files (x86)\\PHP\\ env.PROCESSOR_ARCHITECTURE=x86 env.PROCESSOR_ARCHITEW6432=AMD64 env.PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 42 Stepping 7, GenuineIntel env.PROCESSOR_LEVEL=6 env.PROCESSOR_REVISION=2a07 env.PROG05202499051=1 env.PROG05202499053=1 env.PROMPT=$P$G env.PSModulePath=C\:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules\\ env.PUBLIC=C\:\\Users\\Public env.Path=C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\PHP\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\jEdit;C\:\\Program Files (x86)\\Common Files\\Acronis\\SnapAPI\\;C\:\\Program Files (x86)\\QuickTime\\QTSystem\\;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\Program Files\\Lucidlogix Technologies\\VIRTU env.ProgramData=C\:\\ProgramData env.ProgramFiles=C\:\\Program Files (x86) env.ProgramFiles(x86)=C\:\\Program Files (x86) env.ProgramW6432=C\:\\Program Files env.QTJAVA=C\:\\Program Files (x86)\\Java\\jre6\\lib\\ext\\QTJava.zip env.SESSIONNAME=Console env.SystemDrive=C\: env.SystemRoot=C\:\\Windows env.TEMP=D\:\\Users\\Kelvin~1\\APPDAT~1\\Local\\Temp env.TMP=D\:\\Users\\Kelvin~1\\APPDAT~1\\Local\\Temp env.USERDOMAIN=blaxland3 env.USERNAME=Kelvin Mo env.USERPROFILE=C\:\\Users\\Kelvin Mo env.WIX=C\:\\Program Files (x86)\\Windows Installer XML v3.5\\ env.asl.log=Destination\=file;OnFirstLog\=command,environment env.windir=C\:\\Windows file.encoding=Cp1252 file.encoding.pkg=sun.io file.separator=\\ java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment java.awt.printerjob=sun.awt.windows.WPrinterJob java.class.path=;c\:\\Program Files (x86)\\ant\\bin\\..\\lib\\ant-launcher.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-antlr.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-apache-bcel.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-apache-bsf.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-apache-log4j.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-apache-oro.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-apache-regexp.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-apache-resolver.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-apache-xalan2.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-commons-logging.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-commons-net.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-icontract.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-jai.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-javamail.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-jdepend.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-jmf.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-jsch.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-junit.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-junit4.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-launcher.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-netrexx.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-nodeps.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-starteam.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-stylebook.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-swing.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-testutil.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-trax.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-vaj.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-weblogic.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-xalan1.jar;C\:\\Program Files (x86)\\ant\\lib\\ant-xslp.jar;C\:\\Program Files (x86)\\ant\\lib\\ant.jar;C\:\\Program Files (x86)\\ant\\lib\\commons-logging-1.1.jar;C\:\\Program Files (x86)\\ant\\lib\\commons-net-1.4.1.jar;C\:\\Program Files (x86)\\ant\\lib\\j2ssh-ant-0.2.9.jar;C\:\\Program Files (x86)\\ant\\lib\\j2ssh-common-0.2.9.jar;C\:\\Program Files (x86)\\ant\\lib\\j2ssh-core-0.2.9.jar;C\:\\Program Files (x86)\\ant\\lib\\jakarta-oro-2.0.8.jar;C\:\\Program Files (x86)\\ant\\lib\\jsch-0.1.42.jar;C\:\\Program Files (x86)\\ant\\lib\\log4j-1.2.14.jar;C\:\\Program Files (x86)\\ant\\lib\\xercesImpl.jar;C\:\\Program Files (x86)\\ant\\lib\\xml-apis.jar java.class.version=50.0 java.endorsed.dirs=C\:\\Program Files (x86)\\Java\\jre6\\lib\\endorsed java.ext.dirs=C\:\\Program Files (x86)\\Java\\jre6\\lib\\ext;C\:\\Windows\\Sun\\Java\\lib\\ext java.home=C\:\\Program Files (x86)\\Java\\jre6 java.io.tmpdir=D\:\\Users\\Kelvin~1\\APPDAT~1\\Local\\Temp\\ java.library.path=C\:\\Program Files (x86)\\Java\\jre6\\bin;C\:\\Windows\\Sun\\Java\\bin;C\:\\Windows\\system32;C\:\\Windows;C\:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C\:\\Program Files (x86)\\AMD APP\\bin\\x86;C\:\\Program Files (x86)\\PHP\\;C\:\\Windows\\system32;C\:\\Windows;C\:\\Windows\\System32\\Wbem;C\:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C\:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C\:\\Program Files\\jEdit;C\:\\Program Files (x86)\\Common Files\\Acronis\\SnapAPI\\;C\:\\Program Files (x86)\\QuickTime\\QTSystem\\;C\:\\Program Files\\TortoiseSVN\\bin;C\:\\Program Files\\Lucidlogix Technologies\\VIRTU;. java.runtime.name=Java(TM) SE Runtime Environment java.runtime.version=1.6.0_29-b11 java.specification.name=Java Platform API Specification java.specification.vendor=Sun Microsystems Inc. java.specification.version=1.6 java.vendor=Sun Microsystems Inc. java.vendor.url=http\://java.sun.com/ java.vendor.url.bug=http\://java.sun.com/cgi-bin/bugreport.cgi java.version=1.6.0_29 java.vm.info=mixed mode, sharing java.vm.name=Java HotSpot(TM) Client VM java.vm.specification.name=Java Virtual Machine Specification java.vm.specification.vendor=Sun Microsystems Inc. java.vm.specification.version=1.0 java.vm.vendor=Sun Microsystems Inc. java.vm.version=20.4-b02 line.separator=\r\n os.arch=x86 os.name=Windows 7 os.version=6.1 path.separator=; pear.path=${env.PHP_PEAR_BIN_DIR}/pear.bat phing.path=${env.PHP_PEAR_BIN_DIR}/phing.bat php.path=${env.phpCli} phpdoc.dest.path=phpdoc phpdoc.ini.path=C\:/Program Files/PHPDoc/phpDocumentor.ini phpdoc.path=C\:/Program Files/PHPDoc/phpdoc simpleid.path=simpleid-release simpleid.versiondetect=simpleid-release/www/version.inc ssh.sourceforge.key.file=sourceforge.openssh sun.arch.data.model=32 sun.boot.class.path=C\:\\Program Files (x86)\\Java\\jre6\\lib\\resources.jar;C\:\\Program Files (x86)\\Java\\jre6\\lib\\rt.jar;C\:\\Program Files (x86)\\Java\\jre6\\lib\\sunrsasign.jar;C\:\\Program Files (x86)\\Java\\jre6\\lib\\jsse.jar;C\:\\Program Files (x86)\\Java\\jre6\\lib\\jce.jar;C\:\\Program Files (x86)\\Java\\jre6\\lib\\charsets.jar;C\:\\Program Files (x86)\\Java\\jre6\\lib\\modules\\jdk.boot.jar;C\:\\Program Files (x86)\\Java\\jre6\\classes sun.boot.library.path=C\:\\Program Files (x86)\\Java\\jre6\\bin sun.cpu.endian=little sun.cpu.isalist=pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86 sun.desktop=windows sun.io.unicode.encoding=UnicodeLittle sun.java.command=org.apache.tools.ant.launch.Launcher sourceforge-release sun.java.launcher=SUN_STANDARD sun.jnu.encoding=Cp1252 sun.management.compiler=HotSpot Client Compiler sun.os.patch.level=Service Pack 1 user.country=AU user.dir=C\:\\Users\\Kelvin Mo\\Documents\\Programming\\simpleid user.home=D\:\\Users\\Kelvin Mo user.language=en user.name=Kelvin Mo user.timezone= user.variant= simpleid/COPYING-xtemplate.txt0000644000175000017500000006334011710103700016004 0ustar danieldaniel$HeadURL: https://xtpl.svn.sourceforge.net/svnroot/xtpl/branches/php4/license.txt $ $Id: COPYING-xtemplate.txt 113 2009-05-16 01:25:13Z kmo $ XTemplate is dual licensed using BSD and LGPL. In plain English, you do not need to distribute your application in source code form, nor do you need to distribute XTemplate source code, provided you follow the rest of terms of the BSD license. For more info about XTemplate, visit http://www.phpxtemplate.org/ BSD Style-License ================= Copyright (c) 2000-2001 Barnab�s Debreceni [cranx@users.sourceforge.net] XTemplate Copyright (c) 2002-2007 Jeremy Coates [cocomp@users.sourceforge.net] XTemplate & CachingXTemplate All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the XTemplate, Barnab�s Debreceni, Jeremy Coates nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. DISCLAIMER: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL XTemplate, Barnab�s Debreceni, Jeremy Coates OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ========================================================== Copyright (c) 2000-2001 Barnab�s Debreceni [cranx@users.sourceforge.net] XTemplate Copyright (c) 2002-2007 Jeremy Coates [cocomp@users.sourceforge.net] XTemplate GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONSsimpleid/cache/0000755000175000017500000000000011710103552013174 5ustar danieldanielsimpleid/extensions/0000755000175000017500000000000011746513176014350 5ustar danieldanielsimpleid/extensions/hooks.inc0000644000175000017500000002162311710103700016145 0ustar danieldaniel * * * * @return array an array of URIs * @since 0.7 */ function hook_xrds_types() { } /** * Processes an authentication request that is not about an identifier. * * The OpenID specifications provides a mechanism for extensions to process * authentication requests that are not about an identifier. Authentication requests * about identifiers are automatically processed by the {@link simpleid_checkid_identity()} * function and the {@link hook_checkid_identity()} hooks. * * Assertion results are coded within SimpleID as an integer between 127 ({@link CHECKID_OK}) * and -127 ({@link CHECKID_PROTOCOL_ERROR}). Positive values indicate a potential * positive assertion (subject to various types of user approval), while negative * values indicate a irrecoverable negative assertion. * * This hook should return one of these values. If the extension is unable to * handle this particular type of authentication request, it should return NULL. * * @param array $request the OpenID request * @param bool $immediate true if openid.mode is checkid_immediate * @return int a return value from the list of possible values returned by * {@link simpleid_checkid_identity()} or NULL * @see simpleid_checkid() */ function hook_checkid($request, $immediate) { } /** * Processes an authentication request where the assertion is potentially * positive. * * Assertion results are coded within SimpleID as an integer between 127 ({@link CHECKID_OK}) * and -127 ({@link CHECKID_PROTOCOL_ERROR}). Positive values indicate a potential * positive assertion (subject to various types of user approval), while negative * values indicate a irrecoverable negative assertion. * * Extensions are able to examine the authentication request to modify change * the assertion result from positive to negative. As SimpleID takes the * minimum from the results returned by this hook, extensions are * not able to change the assertion result from negative to positive. * * If the extension is indifferent to the result of the current authentication * request (e.g. it cannot understand it), it should return NULL. * * This hook is not called at all if SimpleID determines that the assertion * is negative. * * @param array $request the OpenID request * @param string $identity the identity to be checked against * @param bool $immediate true if openid.mode is checkid_immediate * @return int a return value from the list of possible values returned by * {@link simpleid_checkid_identity()} or NULL * @see simpleid_checkid_identity() */ function hook_checkid_identity($request, $identity, $immediate) { } /** * Gets fields and values to be included in the OpenID response. * * For positive assertions, this hook should assume that all user approvals * have been given and return a response array accordingly. The extension has * the opportunity to modify the response what the user has actually approved * in the {@link hook_send() send hook}. * * This hook will need to provide any aliases required. * * An example: * * * $my_uri, * 'openid.' . $alias . '.field' => 'value' * ); * ?> * * * @param bool $assertion true if a positive assertion is made, false otherwise * @param array $request the OpenID request * @return array the fields and values to include */ function hook_response($assertion, $request) { } /** * Gets fields associated with this extension which needs to be signed * * SimpleID automatically handles signing fields required by the OpenID * specification, so only the fields introduced by this extension * needed to be returned by this function. * * The array of fields returned by this function must include any applicable * aliases as required. For example * * * * * * @param array $response the OpenID response to sign * @return array an array of fields to sign */ function hook_signed_fields($response) { } /** * Determines the format in which assertions are sent, when they are sent via * indirect communication. * * The OpenID specification version 2.0 provides for the sending of assertions * via indirect communication. The original specifications provide that the * response should be formatted within the query string. * * Some extensions to the OpenID specification allows the assertion to be * formatted in some other way, e.g. via the fragment. This hook allows * extensions to specify which format the assertion should be sent. * * If the extension is indifferent regarding the format, it should return * null * * @param string $url the URL of the RP to which the response is to be sent * @param array $response the assertion to be sent * @return int one of OPENID_RESPONSE_QUERY or OPENID_RESPONSE_FRAGMENT or NULL */ function hook_indirect_response($url, $response) { } /** * Provides additional form items when displaying the login form * * @param string $destination he SimpleID location to which the user is directed * if login is successful * @param string $state the current SimpleID state, if required by the location * @see user_login_form() */ function hook_user_login_form($destination, $state) { } /** * Provides additional form items when displaying the relying party consent * form * * * @param array $request the OpenID request * @param array $response the proposed OpenID response * @param array $rp the user's preferences saved with this relying party * @return string HTML code to be inserted into the verification form * @see simpleid_consent_form() * @deprecated Use {@link hook_consent_form()} */ function hook_rp_form($request, $response, $rp) { } /** * Provides additional form items when displaying the relying party consent * form * * * @param array $request the OpenID request * @param array $response the proposed OpenID response * @param array $rp the user's preferences saved with this relying party * @return string HTML code to be inserted into the verification form * @see simpleid_consent_form() * @since 0.8 */ function hook_consent_form($request, $response, $rp) { } /** * Processes the relying party consent form. * * This provides the extension with the opportunity to: * * - modify the OpenID response based on the user's preferences by editing * $response * - save the user's preferences by editing $rp * * @param array $form_request the data submitted by the user in the relying * party verification form * @param array &$response pointer to the proposed OpenID response * @param array &$rp pointer to the user's preferences saved with this relying party * @deprecated Use {@link hook_consent()} * */ function hook_send($form_request, &$response, &$rp) { } /** * Processes the relying party verification form. * * This provides the extension with the opportunity to: * * - modify the OpenID response based on the user's preferences by editing * $response * - save the user's preferences by editing $rp * * @param array $form_request the data submitted by the user in the relying * party verification form * @param array &$response pointer to the proposed OpenID response * @param array &$rp pointer to the user's preferences saved with this relying party * @since 0.8 * */ function hook_consent($form_request, &$response, &$rp) { } /** * Return any additional items provided by the extension to be appended to the * Simpleweb route array. * * @see simpleweb.inc * @see simpleid_start() * @return array the routes array * @since 0.7 */ function hook_routes() { } /** * Returns additional blocks to be displayed in the user's dashboard. * * A block is coded as an array in accordance with the specifications set * out in {@link page.inc}. * * This hook should return an array of blocks, i.e. an array of * arrays. * * @see page_dashboard() * @return array an array of blocks to add to the user's dashboard * @since 0.7 */ function hook_page_dashboard() { } /** * Returns additional blocks to be displayed in the user's profile page. * * A block is coded as an array in accordance with the specifications set * out in {@link page.inc}. * * This hook should return an array of blocks, i.e. an array of * arrays. * * @see page_profile() * @return array an array of blocks to add to the user's profile page * @since 0.7 */ function hook_page_profile() { } ?> simpleid/README.txt0000644000175000017500000000465411710103700013633 0ustar danieldaniel// $Id: README.txt 349 2010-12-19 00:15:12Z kmo $ SimpleID ======== SimpleID is a simple, personal OpenID provider written in PHP. Latest Version -------------- The latest version of SimpleID can be found in the SimpleID web page at Upgrading --------- General upgrade instructions can be found in UPGRADE.txt. IMPORTANT: SimpleID version 0.7 introduced numerous changes. A manual upgrading process is required. If you are upgrading from an earlier version of SimpleID, please read UPGRADE.txt for upgrade instructions. IMPORTANT: SimpleID version 0.6 introduced a new log in mechanism. If you are upgrading from an earlier version of SimpleID, please read UPGRADE.txt for upgrade instructions. Installation ------------ For installation instructions, please see the SimpleID Getting Started Guide at . Documentation ------------- Documentation for SimpleID can be found at . Licensing --------- Licensing information for SimpleID can be found in the file COPYING.txt. Donate ------ If you enjoy using SimpleID, please consider making a donation to support the ongoing development work. To find out more on how to donate, visit . Your donation is very much appreciated. Acknowledgements ---------------- SimpleID includes code from the Drupal OpenID module , written by Rowan Kerr and James Walker . SimpleID uses the XTemplate PHP templating engine , written by Barnabas Debreceni and Jeremy Coates. Licensing information for this library can be found in COPYING-xtemplate.txt. SimpleID uses the famfamfam Silk icon set , designed by Mark James. The icon set is licensed is licensed under a Creative Commons Attribution 2.5 License . SimpleID uses the jQuery JavaScript library , by John Resig and the jQuery team. Licensing information for this library can be found at . SimpleID uses a JavaScript MD5 message digest library , written by Paul Johnston, Greg Holt, Andrew Kepert, Ydnar, Lostinet. Licensing information for this library can be found in COPYING-md5.js.txt. simpleid/COPYING.txt0000644000175000017500000004321111710103700013776 0ustar danieldaniel// $Id: COPYING.txt 113 2009-05-16 01:25:13Z kmo $ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. simpleid/CHANGELOG.txt0000644000175000017500000001424311710103700014160 0ustar danieldaniel// $Id: CHANGELOG.txt 512 2012-01-25 22:42:56Z kmo $ SimpleID 0.8.1 -------------- - Bug fixes: * #77 Incorrect detection of register_globals PHP configuration variable * #86 PHP syntax warnings in filesystem.store.inc * #88 Updated URL to Simple Registration Extension specification in example.identity.dist * #91 Missing parameters in simpleid_checkid_error() * #92 Corrected path handling in simpleweb * #98 Missing global variable in simpleid_openid_consent() - Improvements to user interface: * #94 Switch redirects from form-based to HTTP header-based - Improvements to the PAPE extension * #95 Added private personal identifiers SimpleID 0.8 ------------ - Improved OpenID specification compliance: * Added read-only support for attribute exchange extension * Addes support for provider authentication policy extension - Improvements to user interfaces: * #14 Added support for clean URLs * #18 Improved comformance to HTML specifications in user interface * #19 For OpenID immediate requests, assertion will not fail simply because return_to has not been verified * #23 Optional support for browsers to save SimpleID passwords - Improvements to SimpleID internals: * Refactored function names * Refactored function layout in discovery.inc and openid.inc * Opened up identity store code to allow support for non filesystem based identity files * Improved source code documentation - Bug fixes: * #74 Function naming conflict with PECL http module within http.inc SimpleID 0.7.6 -------------- - Fixed directory traversal vulnerability SA-2011-1 (http://simpleid.sourceforge.net/advisories/sa-2011-1) SimpleID 0.7.5 -------------- - Bug fixes: * #61 PHP safe mode causing curl configuration issues * #64 Issue with URL parsing under Simpleweb framework SimpleID 0.7.4 -------------- - Fixed incorrect implementation of fix for PHP's handling of HTTP parameters. SimpleID 0.7.3 -------------- - Bug fixes: * #47 PHP syntax warnings in discovery.inc. * #48 PHP syntax warnings in user.inc. * #50 Fix for PHP's handling of HTTP parameters. SimpleID 0.7.2 -------------- - Bug fixes: * #40 PHP syntax warnings in simpleweb.inc. * #42 PHP syntax warnings in index.php. SimpleID 0.7.1 -------------- - Bug fixes: * Incorrect specification for expiry time for auto login. * Fixed verification of credentials under legacy authentication. * Fixed incorrect signing of Simple Registration Extension response. * Fixed Javascript for digest authentication. * Used Javascript instead of forms for page redirection for better HTTPS user experience. SimpleID 0.7 ------------ - Improved OpenID specification compliance: * Added additional return_to verification using discovery. * Fixed support for SHA256. * Fixed indirect message URL encoding. * Fixed filtering of extension-specific parameters. * Fixed XRDS document for SimpleID. - Preliminary implementation of the OpenID User Interface extension. - Added support for GMP for improved performance for arbitary precision arithmetic operations. - Improved user interface: * Separated Dashboard, My Profile and My Sites pages. * Added "log in as different user" functionality. * CSS improvements. * Added framekiller code. * Support for nicer URLs via mod_rewrite. - Enhanced detection of SSL/TLS for user login page. - Implemented flexible persistent storage system to store user data. - Improved extension framework: major refactoring of hooks available to be utilised by extensions. - Improved URL routing framework: included simpleweb.inc. - Added upgrade script. - Enhanced logging of status and errors. - Enhanced code documentation. SimpleID 0.6.5 -------------- - Bug fixes: * Fixed XSS vulnerability in user login page. * Fixed XRDS-Location HTTP header. SimpleID 0.6.4 -------------- - Fixed user interface bug on trusted sites page (disable Submit button when there are no trusted sites). SimpleID 0.6.3 -------------- - Fixed session_type verification response when using OpenID 1.1 associations. SimpleID 0.6.2 -------------- - Fixed session_type verification issue when using OpenID 1.1 associations. SimpleID 0.6.1 -------------- - Fixed return_to verification issue when using OpenID 1.1 (legacy handling of nonce parameter). SimpleID 0.6 ------------ - Bug fixes: * Fixed syntax errors in openid.inc. * Fixed incorrect error authentication response. - Implemented digest authentication for user login (security enhancements). - Implemented persistent login - Enhanced form security: * Added form token verification. * Enhanced encoding of HTML special characters. - Improved compliance against OpenID specifications: * Added return_to verification. - Changed extension of extensions from .inc to .extension.inc. - Enhanced code documentation. SimpleID 0.5.1 -------------- - Bug fixes: * Removed remnants of maths question (removed in SimpleID 0.5) from user.inc - Included Simple Registration Extension by default SimpleID 0.5 ------------ - Bug fixes: * Removed XSS vulnerabilities * Fixed incorrect processing of Simple Registration Extension parameters * Fixed URL for identifier selection. - The identifier variable is now optional in identity files. SimpleID automatically assigns an identifier to all identities where this is not specified. - Log in security improvements: * Removed requirement to complete a maths question to log in. * Added nonce check into login page to detect repeat attacks. - Improved compliance against OpenID specifications: * Enhanced support for OpenID 2.0. * Enhanced checking of request parameters. * Added support for discovery of SimpleID services via XRDS. - Support for SHA256 where this is compiled into PHP. - Added default profile page and XRDS document for each user. SimpleID 0.2.1 -------------- - Bug fixes: * Removed incorrect and legacy handling of nonce parameter in OpenID 1.1 authentication responses SimpleID 0.2 ------------ - Bug fixes: * Fixed template compile error in Simple Registration Extension. SimpleID 0.1 ------------ - Initial release simpleid/COPYING-md5.js.txt0000644000175000017500000000301011710103700015065 0ustar danieldaniel// $Id: COPYING-md5.js.txt 113 2009-05-16 01:25:13Z kmo $ Copyright (c) 1998 - 2008, Paul Johnston & Contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. simpleid/store/0000755000175000017500000000000011710103552013265 5ustar danieldanielsimpleid/identities/0000755000175000017500000000000011746513176014312 5ustar danieldanielsimpleid/identities/example.identity.dist0000644000175000017500000001136111710103700020437 0ustar danieldaniel; :mode=ini: ; $Id: example.identity.dist 458 2011-10-19 10:06:30Z kmo $ ; ; ; SimpleID identity file. ; ; This file contains all the data associated with an identity. It should ; always be named username.identity, where username is the user name to be used ; when logging into SimpleID. ; ; In this file, if a value contains non-numeric characters, you will need to ; surround it with quotation characters. ; ; ; The OpenID Identifier associated with this identity. This is typically a ; URL, although the OpenID specifications allow the use of URIs and even XRIs. ; ; Relying parties must be able to resolve the identity to obtain the address ; of this SimpleID installation. ; ; WARNING: If you change the OpenID Identifier after you have used it in ; SimpleID, you will need to delete all files named 'identity-*.cache' in the ; cache directory. ; ; Examples: ; http://example.com/ ; http://example.com:8888/ ; http://example.com/myopenid ; https://example.com:8080/myopenid ; identity="http://example.com/" ; ; The password associated with this identity. This password is hashed using ; the MD5 algorithm. ; ; There are various tools available which will give you the MD5 hash of any ; given string. If you have access to the command-line interface of PHP, you ; can run the following command to give you the hash. ; ; php -r "print md5('example password');" ; ; Alternatively, you can upload the following PHP code to your web server, then ; read off the hash with your web browser. (This is recommended only if your ; web server supports secure uploads (e.g. SFTP) and HTTPS, you that your ; password is not sent over the Internet as clear text.) ; ; ; ; Alternatively, Wikipedia (http://en.wikipedia.org/wiki/MD5) has other resources ; on generating this hash. ; pass="c8e24ae844b7cb9381g722ae8209a19a" ; ; Whether this user is given administrative privileges in SimpleID. ; ; This setting has no effect in the current version of SimpleID. However, ; more functionality may be added to SimpleID in future versions which will ; be restricted to SimpleID administrators. ; ; You should grant administrative privileges to at least one user. ; ; If you wish this user to be given administrative privileges, uncomment the ; line below. ; ;administrator=1 ; ; Simple Registration Extension data. ; ; If you want to provide registration data to relying parties which support the ; Simple Registration Extension, uncomment the section below and fill ; in your details. ; ; Further information on the Simple Registration Extension can be found at ; http://simpleid.sourceforge.net/documentation/using-simpleid/extensions/simple-registration-extension ; ; Note, you must also enable the Simple Registration Extension in SimpleID. To ; do this, make sure the SIMPLEID_EXTENSIONS option in config.inc contains ; sreg ; ;[sreg] ;nickname="Example" ;email="example@example.com" ;fullname="Example" ;dob="2000-00-00" ;gender="M" ;postcode="1234" ;country="en" ;language="au" ;timezone="Australia/Sydney" ; ; Attribute Exchange Extension data. ; ; If you want to provide personal identity information data to relying parties ; which support the Attribute Exchange Extension, uncomment the section below ; and fill in your details. ; ; The format of this section is attribute type URI=attribute value. Examples ; are given below. ; ; For a full list of attributes, see http://openid.net/specs/openid-attribute-properties-list-1_0-01.html ; ; Note if you have already uncommented and filled out the Simple Registration ; Extension data above, you do not need to fill out the corresponding ; attributes again in the section below. SimpleID will pick these up ; automatically, including: ; ; http://axschema.org/namePerson/friendly ; http://axschema.org/contact/email ; http://axschema.org/namePerson ; http://axschema.org/birthDate ; http://axschema.org/person/gender ; http://axschema.org/contact/postalCode/home ; http://axschema.org/contact/country/home ; http://axschema.org/pref/language ; http://axschema.org/pref/timezone ; http://openid.net/schema/namePerson/friendly ; http://openid.net/schema/contact/internet/email ; http://openid.net/schema/gender ; http://openid.net/schema/contact/postalCode/home ; http://openid.net/schema/contact/country/home ; http://openid.net/schema/language/pref ; http://openid.net/schema/timezone ; ; Note, you must also enable the Attribute Exchange Extension in SimpleID. To ; do this, make sure the SIMPLEID_EXTENSIONS option in config.inc contains ; ax ; ;[ax] ;http://openid.net/schema/company/name="Example Company Limited" ;http://openid.net/schema/company/title="Managing Director" ;http://openid.net/schema/contact/web/blog="http://simpleid.sourceforge.net/" tar/0000755000175000017500000000000011663412405011120 5ustar danieldanieltar/simpleid/0000755000175000017500000000000011710103552012717 5ustar danieldanieltar/simpleid/www/0000755000175000017500000000000011710103552013543 5ustar danieldanieltar/simpleid/www/html/0000755000175000017500000000000011710103552014507 5ustar danieldanieltar/simpleid/www/lib/0000755000175000017500000000000011710103552014311 5ustar danieldanieltar/simpleid/www/extensions/0000755000175000017500000000000011663412406015752 5ustar danieldanieltar/simpleid/www/extensions/ui/0000755000175000017500000000000011710103552016357 5ustar danieldanieltar/simpleid/www/extensions/ax/0000755000175000017500000000000011710103552016352 5ustar danieldanieltar/simpleid/www/extensions/sreg/0000755000175000017500000000000011710103552016702 5ustar danieldanieltar/simpleid/www/extensions/pape/0000755000175000017500000000000011710103552016667 5ustar danieldanieltar/simpleid/cache/0000755000175000017500000000000011663412406013772 5ustar danieldanieltar/simpleid/extensions/0000755000175000017500000000000011710103552015116 5ustar danieldanieltar/simpleid/store/0000755000175000017500000000000011663412406014063 5ustar danieldanieltar/simpleid/identities/0000755000175000017500000000000011710103552015060 5ustar danieldaniel