get_role('administrator');
if ($role) $role->add_cap('use_openid_provider');
}
// Add custom OpenID options
add_option( 'openid_enable_commentform', true );
add_option( 'openid_plugin_enabled', true );
add_option( 'openid_plugin_revision', 0 );
add_option( 'openid_db_revision', 0 );
add_option( 'openid_enable_approval', false );
add_option( 'openid_enable_email_mapping', false );
add_option( 'openid_xrds_returnto', true );
add_option( 'openid_xrds_idib', true );
add_option( 'openid_xrds_eaut', true );
add_option( 'openid_comment_displayname_length', 12 );
openid_create_tables();
openid_migrate_old_data();
wp_clear_scheduled_hook('cleanup_openid');
wp_schedule_event(time(), 'hourly', 'cleanup_openid');
// set current revision
update_option( 'openid_plugin_revision', OPENID_PLUGIN_REVISION );
// cleanup old option names
delete_option( 'oid_db_revision' );
delete_option( 'oid_db_version' );
delete_option( 'oid_enable_approval' );
delete_option( 'oid_enable_commentform' );
delete_option( 'oid_enable_email_mapping' );
delete_option( 'oid_enable_foaf' );
delete_option( 'oid_enable_localaccounts' );
delete_option( 'oid_enable_loginform' );
delete_option( 'oid_enable_selfstyle' );
delete_option( 'oid_enable_unobtrusive' );
delete_option( 'oid_plugin_enabled' );
delete_option( 'oid_plugin_revision' );
delete_option( 'oid_plugin_version' );
delete_option( 'oid_trust_root' );
}
/**
* Cleanup expired nonces and associations from the OpenID store.
*/
function openid_cleanup() {
$store =& openid_getStore();
$store->cleanupNonces();
$store->cleanupAssociations();
}
/**
* Called on plugin deactivation. Cleanup all transient data.
*
* @see register_deactivation_hook
*/
function openid_deactivate_plugin() {
wp_clear_scheduled_hook('cleanup_openid');
delete_option('openid_server_associations');
delete_option('openid_server_nonces');
}
/*
* Customer error handler for calls into the JanRain library
*/
function openid_customer_error_handler($errno, $errmsg, $filename, $linenum, $vars) {
if( (2048 & $errno) == 2048 ) return;
if (strpos($errmsg, 'DOMDocument::loadXML') === 0) return;
openid_error( "Library Error $errno: $errmsg in $filename :$linenum");
}
/**
* Send the user to their OpenID provider to authenticate.
*
* @param Auth_OpenID_AuthRequest $auth_request OpenID authentication request object
* @param string $trust_root OpenID trust root
* @param string $return_to URL where the OpenID provider should return the user
*/
function openid_doRedirect($auth_request, $trust_root, $return_to) {
$message = $auth_request->getMessage($trust_root, $return_to, false);
if (Auth_OpenID::isFailure($message)) {
return openid_error('Could not redirect to server: '.$message->message);
}
$_SESSION['openid_return_to'] = $message->getArg(Auth_OpenID_OPENID_NS, 'return_to');
// send 302 redirect or POST
if ($auth_request->shouldSendRedirect()) {
$redirect_url = $auth_request->redirectURL($trust_root, $return_to);
wp_redirect( $redirect_url );
} else {
openid_repost($auth_request->endpoint->server_url, $message->toPostArgs());
}
}
/**
* Finish OpenID Authentication.
*
* @return String authenticated identity URL, or null if authentication failed.
*/
function finish_openid_auth() {
@session_start();
$consumer = openid_getConsumer();
$response = $consumer->complete($_SESSION['openid_return_to']);
unset($_SESSION['openid_return_to']);
openid_response($response);
switch( $response->status ) {
case Auth_OpenID_CANCEL:
openid_message(__('OpenID login was cancelled.', 'openid'));
openid_status('error');
break;
case Auth_OpenID_FAILURE:
openid_message(sprintf(__('OpenID login failed: %s', 'openid'), $response->message));
openid_status('error');
break;
case Auth_OpenID_SUCCESS:
openid_message(__('OpenID login successful', 'openid'));
openid_status('success');
$identity_url = $response->identity_url;
$escaped_url = htmlspecialchars($identity_url, ENT_QUOTES);
return $escaped_url;
default:
openid_message(__('Unknown Status. Bind not successful. This is probably a bug.', 'openid'));
openid_status('error');
}
return null;
}
/**
* Generate a unique WordPress username for the given OpenID URL.
*
* @param string $url OpenID URL to generate username for
* @param boolean $append should we try appending a number if the username is already taken
* @return mixed generated username or null if unable to generate
*/
function openid_generate_new_username($url, $append = true) {
$base = openid_normalize_username($url);
$i='';
while(true) {
$username = openid_normalize_username( $base . $i );
$user = get_userdatabylogin($username);
if ( $user ) {
if (!$append) return null;
$i++;
continue;
}
return $username;
}
}
/**
* Normalize the OpenID URL into a username. This includes rules like:
* - remove protocol prefixes like 'http://' and 'xri://'
* - remove the 'xri.net' domain for i-names
* - substitute certain characters which are not allowed by WordPress
*
* @param string $username username to be normalized
* @return string normalized username
*/
function openid_normalize_username($username) {
$username = preg_replace('|^https?://(xri.net/([^@]!?)?)?|', '', $username);
$username = preg_replace('|^xri://([^@]!?)?|', '', $username);
$username = preg_replace('|/$|', '', $username);
$username = sanitize_user( $username );
$username = preg_replace('|[^a-z0-9 _.\-@]+|i', '-', $username);
return $username;
}
function openid_begin_consumer($url) {
static $request;
@session_start();
if ($request == NULL) {
set_error_handler( 'openid_customer_error_handler');
if (is_email($url)) {
$_SESSION['openid_login_email'] = $url;
set_include_path( dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
require_once 'Auth/Yadis/Email.php';
$mapped_url = Auth_Yadis_Email_getID($url, trailingslashit(get_option('home')));
if ($mapped_url) {
$url = $mapped_url;
}
}
$consumer = openid_getConsumer();
$request = $consumer->begin($url);
restore_error_handler();
}
return $request;
}
/**
* Start the OpenID authentication process.
*
* @param string $claimed_url claimed OpenID URL
* @param action $action OpenID action being performed
* @param array $arguments array of additional arguments to be included in the 'return_to' URL
* @uses apply_filters() Calls 'openid_auth_request_extensions' to gather extensions to be attached to auth request
*/
function openid_start_login( $claimed_url, $action, $arguments = null, $return_to = null) {
if ( empty($claimed_url) ) return; // do nothing.
$auth_request = openid_begin_consumer( $claimed_url );
if ( null === $auth_request ) {
openid_status('error');
openid_message(sprintf(
__('Could not discover an OpenID identity server endpoint at the url: %s', 'openid'),
htmlentities($claimed_url)
));
if( strpos( $claimed_url, '@' ) ) {
openid_message(openid_message() . '
' . __('It looks like you entered an email address, but it '
. 'was not able to be transformed into a valid OpenID.', 'openid'));
}
return;
}
// build return_to URL
if (empty($return_to)) {
$return_to = trailingslashit(get_option('home'));
}
$auth_request->return_to_args['openid_consumer'] = '1';
$auth_request->return_to_args['action'] = $action;
if (is_array($arguments) && !empty($arguments)) {
foreach ($arguments as $k => $v) {
if ($k && $v) {
$auth_request->return_to_args[urlencode($k)] = urlencode($v);
}
}
}
$extensions = apply_filters('openid_auth_request_extensions', array(), $auth_request);
foreach ($extensions as $e) {
if (is_a($e, 'Auth_OpenID_Extension')) {
$auth_request->addExtension($e);
}
}
$trust_root = get_option('home');
if (preg_match('/^https/', $return_to)) {
$trust_root = preg_replace('/^http\:/', 'https:', $trust_root);
}
openid_doRedirect($auth_request, $trust_root, $return_to);
exit(0);
}
/**
* Build an SReg attribute query extension if we've never seen this OpenID before.
*/
function openid_add_sreg_extension($extensions, $auth_request) {
if(!get_user_by_openid($auth_request->endpoint->claimed_id)) {
set_include_path( dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
require_once('Auth/OpenID/SReg.php');
restore_include_path();
$extensions[] = Auth_OpenID_SRegRequest::build(array(),array('nickname','email','fullname'));
}
return $extensions;
}
/**
* Login user with specified identity URL. This will find the WordPress user account connected to this
* OpenID and set it as the current user. Only call this function AFTER you've verified the identity URL.
*
* @param string $identity userID or OpenID to set as current user
* @param boolean $remember should we set the "remember me" cookie
* @return void
*/
function openid_set_current_user($identity, $remember = true) {
if (is_numeric($identity)) {
$user_id = $identity;
} else {
$user_id = get_user_by_openid($identity);
}
if (!$user_id) return;
$user = set_current_user($user_id);
if (function_exists('wp_set_auth_cookie')) {
wp_set_auth_cookie($user->ID, $remember);
} else {
wp_setcookie($user->user_login, md5($user->user_pass), true, '', '', $remember);
}
do_action('wp_login', $user->user_login);
}
/**
* Finish OpenID authentication.
*
* @param string $action login action that is being performed
* @uses do_action() Calls 'openid_finish_auth' hook action after processing the authentication response.
*/
function finish_openid($action) {
$identity_url = finish_openid_auth();
do_action('openid_finish_auth', $identity_url);
global $action;
$action = openid_status();
}
/**
* Create a new WordPress user with the specified identity URL and user data.
*
* @param string $identity_url OpenID to associate with the newly
* created account
* @param array $user_data array of user data
*/
function openid_create_new_user($identity_url, &$user_data) {
global $wpdb;
// Identity URL is new, so create a user
@include_once( ABSPATH . 'wp-admin/upgrade-functions.php'); // 2.1
@include_once( ABSPATH . WPINC . '/registration-functions.php'); // 2.0.4
// use email address for username if URL is from emailtoid.net
if (null != $_SESSION['openid_login_email'] and strpos($identity_url, 'http://emailtoid.net/') === 0) {
if (empty($user_data['user_email'])) {
$user_data['user_email'] = $_SESSION['openid_login_email'];
}
$username = openid_generate_new_username($_SESSION['openid_login_email']);
unset($_SESSION['openid_login_email']);
}
// otherwise, try to use preferred username
if (empty($username) && $user_data['nickname']) {
$username = openid_generate_new_username($user_data['nickname'], false);
}
// finally, build username from OpenID URL
if (empty($username)) {
$username = openid_generate_new_username($identity_url);
}
$user_data['user_login'] = $username;
$user_data['user_pass'] = substr( md5( uniqid( microtime() ) ), 0, 7);
$user_id = wp_insert_user( $user_data );
if( $user_id ) { // created ok
$user_data['ID'] = $user_id;
// XXX this all looks redundant, see openid_set_current_user
$user = new WP_User( $user_id );
if( ! wp_login( $user->user_login, $user_data['user_pass'] ) ) {
openid_message(__('User was created fine, but wp_login() for the new user failed. This is probably a bug.', 'openid'));
openid_action('error');
openid_error(openid_message());
return;
}
// notify of user creation
wp_new_user_notification( $user->user_login );
wp_clearcookie();
wp_setcookie( $user->user_login, md5($user->user_pass), true, '', '', true );
// Bind the provided identity to the just-created user
openid_add_user_identity($user_id, $identity_url);
openid_status('redirect');
if ( !$user->has_cap('edit_posts') ) $redirect_to = '/wp-admin/profile.php';
} else {
// failed to create user for some reason.
openid_message(__('OpenID authentication successful, but failed to create WordPress user. This is probably a bug.', 'openid'));
openid_status('error');
openid_error(openid_message());
}
}
/**
* Get user data for the given identity URL. Data is returned as an associative array with the keys:
* ID, user_url, user_nicename, display_name
*
* Multiple soures of data may be available and are attempted in the following order:
* - OpenID Attribute Exchange !! not yet implemented
* - OpenID Simple Registration
* - hCard discovery !! not yet implemented
* - default to identity URL
*
* @param string $identity_url OpenID to get user data about
* @return array user data
* @uses apply_filters() Calls 'openid_user_data' to gather profile data associated with the identity URL
*/
function openid_get_user_data($identity_url) {
$data = array(
'ID' => null,
'user_url' => $identity_url,
'user_nicename' => $identity_url,
'display_name' => $identity_url
);
// create proper website URL if OpenID is an i-name
if (preg_match('/^[\=\@\+].+$/', $identity_url)) {
$data['user_url'] = 'http://xri.net/' . $identity_url;
}
$data = apply_filters('openid_user_data', $data, $identity_url);
// if display_name is still the same as the URL, clean that up a bit
if ($data['display_name'] == $identity_url) {
$parts = parse_url($identity_url);
if ($parts !== false) {
$data['display_name'] = preg_replace('/^www./', '', $parts['host']) . substr($parts['path'], 0, get_option('openid_comment_displayname_length'));
}
}
return $data;
}
/**
* Retrieve user data from OpenID Attribute Exchange.
*
* @param string $identity_url OpenID to get user data about
* @param reference $data reference to user data array
* @see get_user_data
*/
function openid_get_user_data_ax($data, $identity_url) {
// TODO implement attribute exchange
return $data;
}
/**
* Retrieve user data from OpenID Simple Registration.
*
* @param string $identity_url OpenID to get user data about
* @param reference $data reference to user data array
* @see get_user_data
*/
function openid_get_user_data_sreg($data, $identity_url) {
require_once(dirname(__FILE__) . '/Auth/OpenID/SReg.php');
$response = openid_response();
$sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($response);
$sreg = $sreg_resp->contents();
if (!$sreg) return $data;
if (array_key_exists('email', $sreg) && $sreg['email']) {
$data['user_email'] = $sreg['email'];
}
if (array_key_exists('nickname', $sreg) && $sreg['nickname']) {
$data['nickname'] = $sreg['nickname'];
$data['user_nicename'] = $sreg['nickname'];
$data['display_name'] = $sreg['nickname'];
}
if (array_key_exists('fullname', $sreg) && $sreg['fullname']) {
$namechunks = explode( ' ', $sreg['fullname'], 2 );
if( isset($namechunks[0]) ) $data['first_name'] = $namechunks[0];
if( isset($namechunks[1]) ) $data['last_name'] = $namechunks[1];
$data['display_name'] = $sreg['fullname'];
}
return $data;;
}
/**
* Retrieve user data from hCard discovery.
*
* @param string $identity_url OpenID to get user data about
* @param reference $data reference to user data array
* @see get_user_data
*/
function openid_get_user_data_hcard($data, $identity_url) {
// TODO implement hcard discovery
return $data;
}
/**
*
* @uses apply_filters() Calls 'openid_consumer_return_urls' to collect return_to URLs to be included in XRDS document.
*/
function openid_consumer_xrds_simple($xrds) {
if (get_option('openid_xrds_returnto')) {
// OpenID Consumer Service
$return_urls = array_unique(apply_filters('openid_consumer_return_urls', array()));
if (!empty($return_urls)) {
$xrds = xrds_add_simple_service($xrds, 'OpenID Consumer Service', 'http://specs.openid.net/auth/2.0/return_to', $return_urls);
}
}
if (get_option('openid_xrds_idib')) {
// Identity in the Browser Login Service
$xrds = xrds_add_service($xrds, 'main', 'Identity in the Browser Login Service',
array(
'Type' => array(array('content' => 'http://specs.openid.net/idib/1.0/login') ),
'URI' => array(
array(
'simple:httpMethod' => 'POST',
'content' => site_url('/wp-login.php', 'login_post'),
),
),
)
);
// Identity in the Browser Indicator Service
$xrds = xrds_add_simple_service($xrds, 'Identity in the Browser Indicator Service',
'http://specs.openid.net/idib/1.0/indicator', site_url('/') . '?openid_check_login');
}
return $xrds;
}
/**
* Parse the WordPress request. If the pagename is 'openid_consumer', then the request
* is an OpenID response and should be handled accordingly.
*
* @param WP $wp WP instance for the current request
*/
function openid_parse_idib_request($wp) {
if (array_key_exists('openid_check_login', $_REQUEST)) {
echo is_user_logged_in() ? 'true' : 'false';
exit;
}
}
/**
* Delete user.
*/
function delete_user_openids($userid) {
openid_drop_all_identities($userid);
}
function openid_add_user_identity($user_id, $identity_url) {
openid_add_identity($user_id, $identity_url);
}
function openid_status($new = null) {
static $status;
return ($new == null) ? $status : $status = $new;
}
function openid_message($new = null) {
static $message;
return ($new == null) ? $message : $message = $new;
}
function openid_response($new = null) {
static $response;
return ($new == null) ? $response : $response = $new;
}
function openid_enabled($new = null) {
static $enabled;
if ($enabled == null) $enabled = true;
return ($new == null) ? $enabled : $enabled = $new;
}
/**
* Send HTTP post through the user-agent. If javascript is not supported, the
* user will need to click on a "continue" button.
*
* @param string $action form action (URL to POST form to)
* @param array $parameters key-value pairs of parameters to include in the form
* @uses do_action() Calls 'openid_page_head' hook action
*/
function openid_repost($action, $parameters) {
$html = '