forked from GNUsocial/gnu-social
Move OpenID-related files to OpenID plugin directory
As a first step to pluginizing our OpenID support, I've moved the important OpenID-related files to a dedicated plugin directory. Many of these classes are still referred to by libraries that are still in core.
This commit is contained in:
25
plugins/OpenID/User_openid.php
Normal file
25
plugins/OpenID/User_openid.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* Table Definition for user_openid
|
||||
*/
|
||||
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
|
||||
|
||||
class User_openid extends Memcached_DataObject
|
||||
{
|
||||
###START_AUTOCODE
|
||||
/* the code below is auto generated do not remove the above tag */
|
||||
|
||||
public $__table = 'user_openid'; // table name
|
||||
public $canonical; // varchar(255) primary_key not_null
|
||||
public $display; // varchar(255) unique_key not_null
|
||||
public $user_id; // int(4) not_null
|
||||
public $created; // datetime() not_null
|
||||
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
||||
|
||||
/* Static get */
|
||||
function staticGet($k,$v=null)
|
||||
{ return Memcached_DataObject::staticGet('User_openid',$k,$v); }
|
||||
|
||||
/* the code above is auto generated do not remove the tag below */
|
||||
###END_AUTOCODE
|
||||
}
|
185
plugins/OpenID/finishaddopenid.php
Normal file
185
plugins/OpenID/finishaddopenid.php
Normal file
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Complete adding an OpenID
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category Settings
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @copyright 2008-2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/openid.php';
|
||||
|
||||
/**
|
||||
* Complete adding an OpenID
|
||||
*
|
||||
* Handle the return from an OpenID verification
|
||||
*
|
||||
* @category Settings
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
class FinishaddopenidAction extends Action
|
||||
{
|
||||
var $msg = null;
|
||||
|
||||
/**
|
||||
* Handle the redirect back from OpenID confirmation
|
||||
*
|
||||
* Check to see if the user's logged in, and then try
|
||||
* to use the OpenID login system.
|
||||
*
|
||||
* @param array $args $_REQUEST arguments
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
if (!common_logged_in()) {
|
||||
$this->clientError(_('Not logged in.'));
|
||||
} else {
|
||||
$this->tryLogin();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to log in using OpenID
|
||||
*
|
||||
* Check the OpenID for validity; potentially store it.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function tryLogin()
|
||||
{
|
||||
$consumer =& oid_consumer();
|
||||
|
||||
$response = $consumer->complete(common_local_url('finishaddopenid'));
|
||||
|
||||
if ($response->status == Auth_OpenID_CANCEL) {
|
||||
$this->message(_('OpenID authentication cancelled.'));
|
||||
return;
|
||||
} else if ($response->status == Auth_OpenID_FAILURE) {
|
||||
// Authentication failed; display the error message.
|
||||
$this->message(sprintf(_('OpenID authentication failed: %s'),
|
||||
$response->message));
|
||||
} else if ($response->status == Auth_OpenID_SUCCESS) {
|
||||
|
||||
$display = $response->getDisplayIdentifier();
|
||||
$canonical = ($response->endpoint && $response->endpoint->canonicalID) ?
|
||||
$response->endpoint->canonicalID : $display;
|
||||
|
||||
$sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($response);
|
||||
|
||||
if ($sreg_resp) {
|
||||
$sreg = $sreg_resp->contents();
|
||||
}
|
||||
|
||||
$cur =& common_current_user();
|
||||
|
||||
$other = oid_get_user($canonical);
|
||||
|
||||
if ($other) {
|
||||
if ($other->id == $cur->id) {
|
||||
$this->message(_('You already have this OpenID!'));
|
||||
} else {
|
||||
$this->message(_('Someone else already has this OpenID.'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// start a transaction
|
||||
|
||||
$cur->query('BEGIN');
|
||||
|
||||
$result = oid_link_user($cur->id, $canonical, $display);
|
||||
|
||||
if (!$result) {
|
||||
$this->message(_('Error connecting user.'));
|
||||
return;
|
||||
}
|
||||
if ($sreg) {
|
||||
if (!oid_update_user($cur, $sreg)) {
|
||||
$this->message(_('Error updating profile'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// success!
|
||||
|
||||
$cur->query('COMMIT');
|
||||
|
||||
oid_set_last($display);
|
||||
|
||||
common_redirect(common_local_url('openidsettings'), 303);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a failure message
|
||||
*
|
||||
* Something went wrong. Save the message, and show the page.
|
||||
*
|
||||
* @param string $msg Error message to show
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function message($msg)
|
||||
{
|
||||
$this->message = $msg;
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Title of the page
|
||||
*
|
||||
* @return string title
|
||||
*/
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('OpenID Login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show error message
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showPageNotice()
|
||||
{
|
||||
if ($this->message) {
|
||||
$this->element('p', 'error', $this->message);
|
||||
}
|
||||
}
|
||||
}
|
495
plugins/OpenID/finishopenidlogin.php
Normal file
495
plugins/OpenID/finishopenidlogin.php
Normal file
@@ -0,0 +1,495 @@
|
||||
<?php
|
||||
/*
|
||||
* Laconica - a distributed open-source microblogging tool
|
||||
* Copyright (C) 2008, 2009, Control Yourself, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) { exit(1); }
|
||||
|
||||
require_once(INSTALLDIR.'/lib/openid.php');
|
||||
|
||||
class FinishopenidloginAction extends Action
|
||||
{
|
||||
var $error = null;
|
||||
var $username = null;
|
||||
var $message = null;
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
if (common_is_real_login()) {
|
||||
$this->clientError(_('Already logged in.'));
|
||||
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$token = $this->trimmed('token');
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$this->showForm(_('There was a problem with your session token. Try again, please.'));
|
||||
return;
|
||||
}
|
||||
if ($this->arg('create')) {
|
||||
if (!$this->boolean('license')) {
|
||||
$this->showForm(_('You can\'t register if you don\'t agree to the license.'),
|
||||
$this->trimmed('newname'));
|
||||
return;
|
||||
}
|
||||
$this->createNewUser();
|
||||
} else if ($this->arg('connect')) {
|
||||
$this->connectUser();
|
||||
} else {
|
||||
common_debug(print_r($this->args, true), __FILE__);
|
||||
$this->showForm(_('Something weird happened.'),
|
||||
$this->trimmed('newname'));
|
||||
}
|
||||
} else {
|
||||
$this->tryLogin();
|
||||
}
|
||||
}
|
||||
|
||||
function showPageNotice()
|
||||
{
|
||||
if ($this->error) {
|
||||
$this->element('div', array('class' => 'error'), $this->error);
|
||||
} else {
|
||||
$this->element('div', 'instructions',
|
||||
sprintf(_('This is the first time you\'ve logged into %s so we must connect your OpenID to a local account. You can either create a new account, or connect with your existing account, if you have one.'), common_config('site', 'name')));
|
||||
}
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('OpenID Account Setup');
|
||||
}
|
||||
|
||||
function showForm($error=null, $username=null)
|
||||
{
|
||||
$this->error = $error;
|
||||
$this->username = $username;
|
||||
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
if (!empty($this->message_text)) {
|
||||
$this->element('div', array('class' => 'error'), $this->message_text);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->elementStart('form', array('method' => 'post',
|
||||
'id' => 'account_connect',
|
||||
'action' => common_local_url('finishopenidlogin')));
|
||||
$this->hidden('token', common_session_token());
|
||||
$this->element('h2', null,
|
||||
_('Create new account'));
|
||||
$this->element('p', null,
|
||||
_('Create a new user with this nickname.'));
|
||||
$this->input('newname', _('New nickname'),
|
||||
($this->username) ? $this->username : '',
|
||||
_('1-64 lowercase letters or numbers, no punctuation or spaces'));
|
||||
$this->elementStart('p');
|
||||
$this->element('input', array('type' => 'checkbox',
|
||||
'id' => 'license',
|
||||
'name' => 'license',
|
||||
'value' => 'true'));
|
||||
$this->text(_('My text and files are available under '));
|
||||
$this->element('a', array('href' => common_config('license', 'url')),
|
||||
common_config('license', 'title'));
|
||||
$this->text(_(' except this private data: password, email address, IM address, phone number.'));
|
||||
$this->elementEnd('p');
|
||||
$this->submit('create', _('Create'));
|
||||
$this->element('h2', null,
|
||||
_('Connect existing account'));
|
||||
$this->element('p', null,
|
||||
_('If you already have an account, login with your username and password to connect it to your OpenID.'));
|
||||
$this->input('nickname', _('Existing nickname'));
|
||||
$this->password('password', _('Password'));
|
||||
$this->submit('connect', _('Connect'));
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
|
||||
function tryLogin()
|
||||
{
|
||||
$consumer = oid_consumer();
|
||||
|
||||
$response = $consumer->complete(common_local_url('finishopenidlogin'));
|
||||
|
||||
if ($response->status == Auth_OpenID_CANCEL) {
|
||||
$this->message(_('OpenID authentication cancelled.'));
|
||||
return;
|
||||
} else if ($response->status == Auth_OpenID_FAILURE) {
|
||||
// Authentication failed; display the error message.
|
||||
$this->message(sprintf(_('OpenID authentication failed: %s'), $response->message));
|
||||
} else if ($response->status == Auth_OpenID_SUCCESS) {
|
||||
// This means the authentication succeeded; extract the
|
||||
// identity URL and Simple Registration data (if it was
|
||||
// returned).
|
||||
$display = $response->getDisplayIdentifier();
|
||||
$canonical = ($response->endpoint->canonicalID) ?
|
||||
$response->endpoint->canonicalID : $response->getDisplayIdentifier();
|
||||
|
||||
$sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($response);
|
||||
|
||||
if ($sreg_resp) {
|
||||
$sreg = $sreg_resp->contents();
|
||||
}
|
||||
|
||||
$user = oid_get_user($canonical);
|
||||
|
||||
if ($user) {
|
||||
oid_set_last($display);
|
||||
# XXX: commented out at @edd's request until better
|
||||
# control over how data flows from OpenID provider.
|
||||
# oid_update_user($user, $sreg);
|
||||
common_set_user($user);
|
||||
common_real_login(true);
|
||||
if (isset($_SESSION['openid_rememberme']) && $_SESSION['openid_rememberme']) {
|
||||
common_rememberme($user);
|
||||
}
|
||||
unset($_SESSION['openid_rememberme']);
|
||||
$this->goHome($user->nickname);
|
||||
} else {
|
||||
$this->saveValues($display, $canonical, $sreg);
|
||||
$this->showForm(null, $this->bestNewNickname($display, $sreg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function message($msg)
|
||||
{
|
||||
$this->message_text = $msg;
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function saveValues($display, $canonical, $sreg)
|
||||
{
|
||||
common_ensure_session();
|
||||
$_SESSION['openid_display'] = $display;
|
||||
$_SESSION['openid_canonical'] = $canonical;
|
||||
$_SESSION['openid_sreg'] = $sreg;
|
||||
}
|
||||
|
||||
function getSavedValues()
|
||||
{
|
||||
return array($_SESSION['openid_display'],
|
||||
$_SESSION['openid_canonical'],
|
||||
$_SESSION['openid_sreg']);
|
||||
}
|
||||
|
||||
function createNewUser()
|
||||
{
|
||||
# FIXME: save invite code before redirect, and check here
|
||||
|
||||
if (common_config('site', 'closed')) {
|
||||
$this->clientError(_('Registration not allowed.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$invite = null;
|
||||
|
||||
if (common_config('site', 'inviteonly')) {
|
||||
$code = $_SESSION['invitecode'];
|
||||
if (empty($code)) {
|
||||
$this->clientError(_('Registration not allowed.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$invite = Invitation::staticGet($code);
|
||||
|
||||
if (empty($invite)) {
|
||||
$this->clientError(_('Not a valid invitation code.'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$nickname = $this->trimmed('newname');
|
||||
|
||||
if (!Validate::string($nickname, array('min_length' => 1,
|
||||
'max_length' => 64,
|
||||
'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
|
||||
$this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!User::allowed_nickname($nickname)) {
|
||||
$this->showForm(_('Nickname not allowed.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (User::staticGet('nickname', $nickname)) {
|
||||
$this->showForm(_('Nickname already in use. Try another one.'));
|
||||
return;
|
||||
}
|
||||
|
||||
list($display, $canonical, $sreg) = $this->getSavedValues();
|
||||
|
||||
if (!$display || !$canonical) {
|
||||
$this->serverError(_('Stored OpenID not found.'));
|
||||
return;
|
||||
}
|
||||
|
||||
# Possible race condition... let's be paranoid
|
||||
|
||||
$other = oid_get_user($canonical);
|
||||
|
||||
if ($other) {
|
||||
$this->serverError(_('Creating new account for OpenID that already has a user.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$location = '';
|
||||
if (!empty($sreg['country'])) {
|
||||
if ($sreg['postcode']) {
|
||||
# XXX: use postcode to get city and region
|
||||
# XXX: also, store postcode somewhere -- it's valuable!
|
||||
$location = $sreg['postcode'] . ', ' . $sreg['country'];
|
||||
} else {
|
||||
$location = $sreg['country'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($sreg['fullname']) && mb_strlen($sreg['fullname']) <= 255) {
|
||||
$fullname = $sreg['fullname'];
|
||||
} else {
|
||||
$fullname = '';
|
||||
}
|
||||
|
||||
if (!empty($sreg['email']) && Validate::email($sreg['email'], true)) {
|
||||
$email = $sreg['email'];
|
||||
} else {
|
||||
$email = '';
|
||||
}
|
||||
|
||||
# XXX: add language
|
||||
# XXX: add timezone
|
||||
|
||||
$args = array('nickname' => $nickname,
|
||||
'email' => $email,
|
||||
'fullname' => $fullname,
|
||||
'location' => $location);
|
||||
|
||||
if (!empty($invite)) {
|
||||
$args['code'] = $invite->code;
|
||||
}
|
||||
|
||||
$user = User::register($args);
|
||||
|
||||
$result = oid_link_user($user->id, $canonical, $display);
|
||||
|
||||
oid_set_last($display);
|
||||
common_set_user($user);
|
||||
common_real_login(true);
|
||||
if (isset($_SESSION['openid_rememberme']) && $_SESSION['openid_rememberme']) {
|
||||
common_rememberme($user);
|
||||
}
|
||||
unset($_SESSION['openid_rememberme']);
|
||||
common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)),
|
||||
303);
|
||||
}
|
||||
|
||||
function connectUser()
|
||||
{
|
||||
$nickname = $this->trimmed('nickname');
|
||||
$password = $this->trimmed('password');
|
||||
|
||||
if (!common_check_user($nickname, $password)) {
|
||||
$this->showForm(_('Invalid username or password.'));
|
||||
return;
|
||||
}
|
||||
|
||||
# They're legit!
|
||||
|
||||
$user = User::staticGet('nickname', $nickname);
|
||||
|
||||
list($display, $canonical, $sreg) = $this->getSavedValues();
|
||||
|
||||
if (!$display || !$canonical) {
|
||||
$this->serverError(_('Stored OpenID not found.'));
|
||||
return;
|
||||
}
|
||||
|
||||
$result = oid_link_user($user->id, $canonical, $display);
|
||||
|
||||
if (!$result) {
|
||||
$this->serverError(_('Error connecting user to OpenID.'));
|
||||
return;
|
||||
}
|
||||
|
||||
oid_update_user($user, $sreg);
|
||||
oid_set_last($display);
|
||||
common_set_user($user);
|
||||
common_real_login(true);
|
||||
if (isset($_SESSION['openid_rememberme']) && $_SESSION['openid_rememberme']) {
|
||||
common_rememberme($user);
|
||||
}
|
||||
unset($_SESSION['openid_rememberme']);
|
||||
$this->goHome($user->nickname);
|
||||
}
|
||||
|
||||
function goHome($nickname)
|
||||
{
|
||||
$url = common_get_returnto();
|
||||
if ($url) {
|
||||
# We don't have to return to it again
|
||||
common_set_returnto(null);
|
||||
} else {
|
||||
$url = common_local_url('all',
|
||||
array('nickname' =>
|
||||
$nickname));
|
||||
}
|
||||
common_redirect($url, 303);
|
||||
}
|
||||
|
||||
function bestNewNickname($display, $sreg)
|
||||
{
|
||||
|
||||
# Try the passed-in nickname
|
||||
|
||||
if (!empty($sreg['nickname'])) {
|
||||
$nickname = $this->nicknamize($sreg['nickname']);
|
||||
if ($this->isNewNickname($nickname)) {
|
||||
return $nickname;
|
||||
}
|
||||
}
|
||||
|
||||
# Try the full name
|
||||
|
||||
if (!empty($sreg['fullname'])) {
|
||||
$fullname = $this->nicknamize($sreg['fullname']);
|
||||
if ($this->isNewNickname($fullname)) {
|
||||
return $fullname;
|
||||
}
|
||||
}
|
||||
|
||||
# Try the URL
|
||||
|
||||
$from_url = $this->openidToNickname($display);
|
||||
|
||||
if ($from_url && $this->isNewNickname($from_url)) {
|
||||
return $from_url;
|
||||
}
|
||||
|
||||
# XXX: others?
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function isNewNickname($str)
|
||||
{
|
||||
if (!Validate::string($str, array('min_length' => 1,
|
||||
'max_length' => 64,
|
||||
'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
|
||||
return false;
|
||||
}
|
||||
if (!User::allowed_nickname($str)) {
|
||||
return false;
|
||||
}
|
||||
if (User::staticGet('nickname', $str)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function openidToNickname($openid)
|
||||
{
|
||||
if (Auth_Yadis_identifierScheme($openid) == 'XRI') {
|
||||
return $this->xriToNickname($openid);
|
||||
} else {
|
||||
return $this->urlToNickname($openid);
|
||||
}
|
||||
}
|
||||
|
||||
# We try to use an OpenID URL as a legal Laconica user name in this order
|
||||
# 1. Plain hostname, like http://evanp.myopenid.com/
|
||||
# 2. One element in path, like http://profile.typekey.com/EvanProdromou/
|
||||
# or http://getopenid.com/evanprodromou
|
||||
|
||||
function urlToNickname($openid)
|
||||
{
|
||||
static $bad = array('query', 'user', 'password', 'port', 'fragment');
|
||||
|
||||
$parts = parse_url($openid);
|
||||
|
||||
# If any of these parts exist, this won't work
|
||||
|
||||
foreach ($bad as $badpart) {
|
||||
if (array_key_exists($badpart, $parts)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
# We just have host and/or path
|
||||
|
||||
# If it's just a host...
|
||||
if (array_key_exists('host', $parts) &&
|
||||
(!array_key_exists('path', $parts) || strcmp($parts['path'], '/') == 0))
|
||||
{
|
||||
$hostparts = explode('.', $parts['host']);
|
||||
|
||||
# Try to catch common idiom of nickname.service.tld
|
||||
|
||||
if ((count($hostparts) > 2) &&
|
||||
(strlen($hostparts[count($hostparts) - 2]) > 3) && # try to skip .co.uk, .com.au
|
||||
(strcmp($hostparts[0], 'www') != 0))
|
||||
{
|
||||
return $this->nicknamize($hostparts[0]);
|
||||
} else {
|
||||
# Do the whole hostname
|
||||
return $this->nicknamize($parts['host']);
|
||||
}
|
||||
} else {
|
||||
if (array_key_exists('path', $parts)) {
|
||||
# Strip starting, ending slashes
|
||||
$path = preg_replace('@/$@', '', $parts['path']);
|
||||
$path = preg_replace('@^/@', '', $path);
|
||||
if (strpos($path, '/') === false) {
|
||||
return $this->nicknamize($path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function xriToNickname($xri)
|
||||
{
|
||||
$base = $this->xriBase($xri);
|
||||
|
||||
if (!$base) {
|
||||
return null;
|
||||
} else {
|
||||
# =evan.prodromou
|
||||
# or @gratis*evan.prodromou
|
||||
$parts = explode('*', substr($base, 1));
|
||||
return $this->nicknamize(array_pop($parts));
|
||||
}
|
||||
}
|
||||
|
||||
function xriBase($xri)
|
||||
{
|
||||
if (substr($xri, 0, 6) == 'xri://') {
|
||||
return substr($xri, 6);
|
||||
} else {
|
||||
return $xri;
|
||||
}
|
||||
}
|
||||
|
||||
# Given a string, try to make it work as a nickname
|
||||
|
||||
function nicknamize($str)
|
||||
{
|
||||
$str = preg_replace('/\W/', '', $str);
|
||||
return strtolower($str);
|
||||
}
|
||||
}
|
280
plugins/OpenID/openid.php
Normal file
280
plugins/OpenID/openid.php
Normal file
@@ -0,0 +1,280 @@
|
||||
<?php
|
||||
/*
|
||||
* Laconica - a distributed open-source microblogging tool
|
||||
* Copyright (C) 2008, 2009, Control Yourself, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) { exit(1); }
|
||||
|
||||
require_once(INSTALLDIR.'/classes/User_openid.php');
|
||||
|
||||
require_once('Auth/OpenID.php');
|
||||
require_once('Auth/OpenID/Consumer.php');
|
||||
require_once('Auth/OpenID/SReg.php');
|
||||
require_once('Auth/OpenID/MySQLStore.php');
|
||||
|
||||
# About one year cookie expiry
|
||||
|
||||
define('OPENID_COOKIE_EXPIRY', round(365.25 * 24 * 60 * 60));
|
||||
define('OPENID_COOKIE_KEY', 'lastusedopenid');
|
||||
|
||||
function oid_store()
|
||||
{
|
||||
static $store = null;
|
||||
if (!$store) {
|
||||
# Can't be called statically
|
||||
$user = new User();
|
||||
$conn = $user->getDatabaseConnection();
|
||||
$store = new Auth_OpenID_MySQLStore($conn);
|
||||
}
|
||||
return $store;
|
||||
}
|
||||
|
||||
function oid_consumer()
|
||||
{
|
||||
$store = oid_store();
|
||||
$consumer = new Auth_OpenID_Consumer($store);
|
||||
return $consumer;
|
||||
}
|
||||
|
||||
function oid_clear_last()
|
||||
{
|
||||
oid_set_last('');
|
||||
}
|
||||
|
||||
function oid_set_last($openid_url)
|
||||
{
|
||||
common_set_cookie(OPENID_COOKIE_KEY,
|
||||
$openid_url,
|
||||
time() + OPENID_COOKIE_EXPIRY);
|
||||
}
|
||||
|
||||
function oid_get_last()
|
||||
{
|
||||
if (empty($_COOKIE[OPENID_COOKIE_KEY])) {
|
||||
return null;
|
||||
}
|
||||
$openid_url = $_COOKIE[OPENID_COOKIE_KEY];
|
||||
if ($openid_url && strlen($openid_url) > 0) {
|
||||
return $openid_url;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function oid_link_user($id, $canonical, $display)
|
||||
{
|
||||
|
||||
$oid = new User_openid();
|
||||
$oid->user_id = $id;
|
||||
$oid->canonical = $canonical;
|
||||
$oid->display = $display;
|
||||
$oid->created = DB_DataObject_Cast::dateTime();
|
||||
|
||||
if (!$oid->insert()) {
|
||||
$err = PEAR::getStaticProperty('DB_DataObject','lastError');
|
||||
common_debug('DB error ' . $err->code . ': ' . $err->message, __FILE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function oid_get_user($openid_url)
|
||||
{
|
||||
$user = null;
|
||||
$oid = User_openid::staticGet('canonical', $openid_url);
|
||||
if ($oid) {
|
||||
$user = User::staticGet('id', $oid->user_id);
|
||||
}
|
||||
return $user;
|
||||
}
|
||||
|
||||
function oid_check_immediate($openid_url, $backto=null)
|
||||
{
|
||||
if (!$backto) {
|
||||
$action = $_REQUEST['action'];
|
||||
$args = common_copy_args($_GET);
|
||||
unset($args['action']);
|
||||
$backto = common_local_url($action, $args);
|
||||
}
|
||||
common_debug('going back to "' . $backto . '"', __FILE__);
|
||||
|
||||
common_ensure_session();
|
||||
|
||||
$_SESSION['openid_immediate_backto'] = $backto;
|
||||
common_debug('passed-in variable is "' . $backto . '"', __FILE__);
|
||||
common_debug('session variable is "' . $_SESSION['openid_immediate_backto'] . '"', __FILE__);
|
||||
|
||||
oid_authenticate($openid_url,
|
||||
'finishimmediate',
|
||||
true);
|
||||
}
|
||||
|
||||
function oid_authenticate($openid_url, $returnto, $immediate=false)
|
||||
{
|
||||
|
||||
$consumer = oid_consumer();
|
||||
|
||||
if (!$consumer) {
|
||||
common_server_error(_('Cannot instantiate OpenID consumer object.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
common_ensure_session();
|
||||
|
||||
$auth_request = $consumer->begin($openid_url);
|
||||
|
||||
// Handle failure status return values.
|
||||
if (!$auth_request) {
|
||||
return _('Not a valid OpenID.');
|
||||
} else if (Auth_OpenID::isFailure($auth_request)) {
|
||||
return sprintf(_('OpenID failure: %s'), $auth_request->message);
|
||||
}
|
||||
|
||||
$sreg_request = Auth_OpenID_SRegRequest::build(// Required
|
||||
array(),
|
||||
// Optional
|
||||
array('nickname',
|
||||
'email',
|
||||
'fullname',
|
||||
'language',
|
||||
'timezone',
|
||||
'postcode',
|
||||
'country'));
|
||||
|
||||
if ($sreg_request) {
|
||||
$auth_request->addExtension($sreg_request);
|
||||
}
|
||||
|
||||
$trust_root = common_root_url(true);
|
||||
$process_url = common_local_url($returnto);
|
||||
|
||||
if ($auth_request->shouldSendRedirect()) {
|
||||
$redirect_url = $auth_request->redirectURL($trust_root,
|
||||
$process_url,
|
||||
$immediate);
|
||||
if (!$redirect_url) {
|
||||
} else if (Auth_OpenID::isFailure($redirect_url)) {
|
||||
return sprintf(_('Could not redirect to server: %s'), $redirect_url->message);
|
||||
} else {
|
||||
common_redirect($redirect_url, 303);
|
||||
}
|
||||
} else {
|
||||
// Generate form markup and render it.
|
||||
$form_id = 'openid_message';
|
||||
$form_html = $auth_request->formMarkup($trust_root, $process_url,
|
||||
$immediate, array('id' => $form_id));
|
||||
|
||||
# XXX: This is cheap, but things choke if we don't escape ampersands
|
||||
# in the HTML attributes
|
||||
|
||||
$form_html = preg_replace('/&/', '&', $form_html);
|
||||
|
||||
// Display an error if the form markup couldn't be generated;
|
||||
// otherwise, render the HTML.
|
||||
if (Auth_OpenID::isFailure($form_html)) {
|
||||
common_server_error(sprintf(_('Could not create OpenID form: %s'), $form_html->message));
|
||||
} else {
|
||||
$action = new AutosubmitAction(); // see below
|
||||
$action->form_html = $form_html;
|
||||
$action->form_id = $form_id;
|
||||
$action->prepare(array('action' => 'autosubmit'));
|
||||
$action->handle(array('action' => 'autosubmit'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Half-assed attempt at a module-private function
|
||||
|
||||
function _oid_print_instructions()
|
||||
{
|
||||
common_element('div', 'instructions',
|
||||
_('This form should automatically submit itself. '.
|
||||
'If not, click the submit button to go to your '.
|
||||
'OpenID provider.'));
|
||||
}
|
||||
|
||||
# update a user from sreg parameters
|
||||
|
||||
function oid_update_user(&$user, &$sreg)
|
||||
{
|
||||
|
||||
$profile = $user->getProfile();
|
||||
|
||||
$orig_profile = clone($profile);
|
||||
|
||||
if ($sreg['fullname'] && strlen($sreg['fullname']) <= 255) {
|
||||
$profile->fullname = $sreg['fullname'];
|
||||
}
|
||||
|
||||
if ($sreg['country']) {
|
||||
if ($sreg['postcode']) {
|
||||
# XXX: use postcode to get city and region
|
||||
# XXX: also, store postcode somewhere -- it's valuable!
|
||||
$profile->location = $sreg['postcode'] . ', ' . $sreg['country'];
|
||||
} else {
|
||||
$profile->location = $sreg['country'];
|
||||
}
|
||||
}
|
||||
|
||||
# XXX save language if it's passed
|
||||
# XXX save timezone if it's passed
|
||||
|
||||
if (!$profile->update($orig_profile)) {
|
||||
common_server_error(_('Error saving the profile.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$orig_user = clone($user);
|
||||
|
||||
if ($sreg['email'] && Validate::email($sreg['email'], true)) {
|
||||
$user->email = $sreg['email'];
|
||||
}
|
||||
|
||||
if (!$user->update($orig_user)) {
|
||||
common_server_error(_('Error saving the user.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class AutosubmitAction extends Action
|
||||
{
|
||||
var $form_html = null;
|
||||
var $form_id = null;
|
||||
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('OpenID Auto-Submit');
|
||||
}
|
||||
|
||||
function showContent()
|
||||
{
|
||||
$this->raw($this->form_html);
|
||||
$this->element('script', null,
|
||||
'$(document).ready(function() { ' .
|
||||
' $(\'#'. $this->form_id .'\').submit(); '.
|
||||
'});');
|
||||
}
|
||||
}
|
131
plugins/OpenID/openidlogin.php
Normal file
131
plugins/OpenID/openidlogin.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/*
|
||||
* Laconica - a distributed open-source microblogging tool
|
||||
* Copyright (C) 2008, 2009, Control Yourself, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) { exit(1); }
|
||||
|
||||
require_once(INSTALLDIR.'/lib/openid.php');
|
||||
|
||||
class OpenidloginAction extends Action
|
||||
{
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
if (common_is_real_login()) {
|
||||
$this->clientError(_('Already logged in.'));
|
||||
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$openid_url = $this->trimmed('openid_url');
|
||||
|
||||
# CSRF protection
|
||||
$token = $this->trimmed('token');
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$this->showForm(_('There was a problem with your session token. Try again, please.'), $openid_url);
|
||||
return;
|
||||
}
|
||||
|
||||
$rememberme = $this->boolean('rememberme');
|
||||
|
||||
common_ensure_session();
|
||||
|
||||
$_SESSION['openid_rememberme'] = $rememberme;
|
||||
|
||||
$result = oid_authenticate($openid_url,
|
||||
'finishopenidlogin');
|
||||
|
||||
if (is_string($result)) { # error message
|
||||
unset($_SESSION['openid_rememberme']);
|
||||
$this->showForm($result, $openid_url);
|
||||
}
|
||||
} else {
|
||||
$openid_url = oid_get_last();
|
||||
$this->showForm(null, $openid_url);
|
||||
}
|
||||
}
|
||||
|
||||
function getInstructions()
|
||||
{
|
||||
if (common_logged_in() && !common_is_real_login() &&
|
||||
common_get_returnto()) {
|
||||
// rememberme logins have to reauthenticate before
|
||||
// changing any profile settings (cookie-stealing protection)
|
||||
return _('For security reasons, please re-login with your ' .
|
||||
'[OpenID](%%doc.openid%%) ' .
|
||||
'before changing your settings.');
|
||||
} else {
|
||||
return _('Login with an [OpenID](%%doc.openid%%) account.');
|
||||
}
|
||||
}
|
||||
|
||||
function showPageNotice()
|
||||
{
|
||||
if ($this->error) {
|
||||
$this->element('div', array('class' => 'error'), $this->error);
|
||||
} else {
|
||||
$instr = $this->getInstructions();
|
||||
$output = common_markup_to_html($instr);
|
||||
$this->elementStart('div', 'instructions');
|
||||
$this->raw($output);
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
}
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('OpenID Login');
|
||||
}
|
||||
|
||||
function showForm($error=null, $openid_url)
|
||||
{
|
||||
$this->error = $error;
|
||||
$this->openid_url = $openid_url;
|
||||
$this->showPage();
|
||||
}
|
||||
|
||||
function showContent() {
|
||||
$formaction = common_local_url('openidlogin');
|
||||
$this->elementStart('form', array('method' => 'post',
|
||||
'id' => 'form_openid_login',
|
||||
'class' => 'form_settings',
|
||||
'action' => $formaction));
|
||||
$this->elementStart('fieldset');
|
||||
$this->element('legend', null, _('OpenID login'));
|
||||
$this->hidden('token', common_session_token());
|
||||
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->input('openid_url', _('OpenID URL'),
|
||||
$this->openid_url,
|
||||
_('Your OpenID URL'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementStart('li', array('id' => 'settings_rememberme'));
|
||||
$this->checkbox('rememberme', _('Remember me'), false,
|
||||
_('Automatically login in the future; ' .
|
||||
'not for shared computers!'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->submit('submit', _('Login'));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
}
|
||||
|
||||
function showLocalNav()
|
||||
{
|
||||
$nav = new LoginGroupNav($this);
|
||||
$nav->show();
|
||||
}
|
||||
}
|
234
plugins/OpenID/openidsettings.php
Normal file
234
plugins/OpenID/openidsettings.php
Normal file
@@ -0,0 +1,234 @@
|
||||
<?php
|
||||
/**
|
||||
* Laconica, the distributed open-source microblogging tool
|
||||
*
|
||||
* Settings for OpenID
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @category Settings
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @copyright 2008-2009 Control Yourself, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/accountsettingsaction.php';
|
||||
require_once INSTALLDIR.'/lib/openid.php';
|
||||
|
||||
/**
|
||||
* Settings for OpenID
|
||||
*
|
||||
* Lets users add, edit and delete OpenIDs from their account
|
||||
*
|
||||
* @category Settings
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
|
||||
class OpenidsettingsAction extends AccountSettingsAction
|
||||
{
|
||||
/**
|
||||
* Title of the page
|
||||
*
|
||||
* @return string Page title
|
||||
*/
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('OpenID settings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructions for use
|
||||
*
|
||||
* @return string Instructions for use
|
||||
*/
|
||||
|
||||
function getInstructions()
|
||||
{
|
||||
return _('[OpenID](%%doc.openid%%) lets you log into many sites' .
|
||||
' with the same user account.'.
|
||||
' Manage your associated OpenIDs from here.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for OpenID management
|
||||
*
|
||||
* We have one form with a few different submit buttons to do different things.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showContent()
|
||||
{
|
||||
$user = common_current_user();
|
||||
|
||||
$this->elementStart('form', array('method' => 'post',
|
||||
'id' => 'form_settings_openid_add',
|
||||
'class' => 'form_settings',
|
||||
'action' =>
|
||||
common_local_url('openidsettings')));
|
||||
$this->elementStart('fieldset', array('id' => 'settings_openid_add'));
|
||||
$this->element('legend', null, _('Add OpenID'));
|
||||
$this->hidden('token', common_session_token());
|
||||
$this->element('p', 'form_guide',
|
||||
_('If you want to add an OpenID to your account, ' .
|
||||
'enter it in the box below and click "Add".'));
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->element('label', array('for' => 'openid_url'),
|
||||
_('OpenID URL'));
|
||||
$this->element('input', array('name' => 'openid_url',
|
||||
'type' => 'text',
|
||||
'id' => 'openid_url'));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
$this->element('input', array('type' => 'submit',
|
||||
'id' => 'settings_openid_add_action-submit',
|
||||
'name' => 'add',
|
||||
'class' => 'submit',
|
||||
'value' => _('Add')));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
|
||||
$oid = new User_openid();
|
||||
|
||||
$oid->user_id = $user->id;
|
||||
|
||||
$cnt = $oid->find();
|
||||
|
||||
if ($cnt > 0) {
|
||||
|
||||
$this->element('h2', null, _('Remove OpenID'));
|
||||
|
||||
if ($cnt == 1 && !$user->password) {
|
||||
|
||||
$this->element('p', 'form_guide',
|
||||
_('Removing your only OpenID '.
|
||||
'would make it impossible to log in! ' .
|
||||
'If you need to remove it, '.
|
||||
'add another OpenID first.'));
|
||||
|
||||
if ($oid->fetch()) {
|
||||
$this->elementStart('p');
|
||||
$this->element('a', array('href' => $oid->canonical),
|
||||
$oid->display);
|
||||
$this->elementEnd('p');
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
$this->element('p', 'form_guide',
|
||||
_('You can remove an OpenID from your account '.
|
||||
'by clicking the button marked "Remove".'));
|
||||
$idx = 0;
|
||||
|
||||
while ($oid->fetch()) {
|
||||
$this->elementStart('form',
|
||||
array('method' => 'POST',
|
||||
'id' => 'form_settings_openid_delete' . $idx,
|
||||
'class' => 'form_settings',
|
||||
'action' =>
|
||||
common_local_url('openidsettings')));
|
||||
$this->elementStart('fieldset');
|
||||
$this->hidden('token', common_session_token());
|
||||
$this->element('a', array('href' => $oid->canonical),
|
||||
$oid->display);
|
||||
$this->element('input', array('type' => 'hidden',
|
||||
'id' => 'openid_url'.$idx,
|
||||
'name' => 'openid_url',
|
||||
'value' => $oid->canonical));
|
||||
$this->element('input', array('type' => 'submit',
|
||||
'id' => 'remove'.$idx,
|
||||
'name' => 'remove',
|
||||
'class' => 'submit remove',
|
||||
'value' => _('Remove')));
|
||||
$this->elementEnd('fieldset');
|
||||
$this->elementEnd('form');
|
||||
$idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a POST request
|
||||
*
|
||||
* Muxes to different sub-functions based on which button was pushed
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handlePost()
|
||||
{
|
||||
// CSRF protection
|
||||
$token = $this->trimmed('token');
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$this->showForm(_('There was a problem with your session token. '.
|
||||
'Try again, please.'));
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->arg('add')) {
|
||||
$result = oid_authenticate($this->trimmed('openid_url'),
|
||||
'finishaddopenid');
|
||||
if (is_string($result)) { // error message
|
||||
$this->showForm($result);
|
||||
}
|
||||
} else if ($this->arg('remove')) {
|
||||
$this->removeOpenid();
|
||||
} else {
|
||||
$this->showForm(_('Something weird happened.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a request to remove an OpenID from the user's account
|
||||
*
|
||||
* Validates input and, if everything is OK, deletes the OpenID.
|
||||
* Reloads the form with a success or error notification.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function removeOpenid()
|
||||
{
|
||||
$openid_url = $this->trimmed('openid_url');
|
||||
|
||||
$oid = User_openid::staticGet('canonical', $openid_url);
|
||||
|
||||
if (!$oid) {
|
||||
$this->showForm(_('No such OpenID.'));
|
||||
return;
|
||||
}
|
||||
$cur = common_current_user();
|
||||
if (!$cur || $oid->user_id != $cur->id) {
|
||||
$this->showForm(_('That OpenID does not belong to you.'));
|
||||
return;
|
||||
}
|
||||
$oid->delete();
|
||||
$this->showForm(_('OpenID removed.'), true);
|
||||
return;
|
||||
}
|
||||
}
|
122
plugins/OpenID/publicxrds.php
Normal file
122
plugins/OpenID/publicxrds.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Public XRDS for OpenID
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Action
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @author Robin Millette <millette@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://laconi.ca/
|
||||
*
|
||||
* Laconica - a distributed open-source microblogging tool
|
||||
* Copyright (C) 2008, 2009, Control Yourself, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/openid.php';
|
||||
|
||||
/**
|
||||
* Public XRDS for OpenID
|
||||
*
|
||||
* @category Action
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @author Robin Millette <millette@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://laconi.ca/
|
||||
*
|
||||
* @todo factor out similarities with XrdsAction
|
||||
*/
|
||||
class PublicxrdsAction extends Action
|
||||
{
|
||||
/**
|
||||
* Is read only?
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class handler.
|
||||
*
|
||||
* @param array $args array of arguments
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
header('Content-Type: application/xrds+xml');
|
||||
$this->startXML();
|
||||
$this->elementStart('XRDS', array('xmlns' => 'xri://$xrds'));
|
||||
$this->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
|
||||
'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
|
||||
'version' => '2.0'));
|
||||
$this->element('Type', null, 'xri://$xrds*simple');
|
||||
foreach (array('finishopenidlogin', 'finishaddopenid') as $finish) {
|
||||
$this->showService(Auth_OpenID_RP_RETURN_TO_URL_TYPE,
|
||||
common_local_url($finish));
|
||||
}
|
||||
$this->elementEnd('XRD');
|
||||
$this->elementEnd('XRDS');
|
||||
$this->endXML();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show service.
|
||||
*
|
||||
* @param string $type XRDS type
|
||||
* @param string $uri URI
|
||||
* @param array $params type parameters, null by default
|
||||
* @param array $sigs type signatures, null by default
|
||||
* @param string $localId local ID, null by default
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showService($type, $uri, $params=null, $sigs=null, $localId=null)
|
||||
{
|
||||
$this->elementStart('Service');
|
||||
if ($uri) {
|
||||
$this->element('URI', null, $uri);
|
||||
}
|
||||
$this->element('Type', null, $type);
|
||||
if ($params) {
|
||||
foreach ($params as $param) {
|
||||
$this->element('Type', null, $param);
|
||||
}
|
||||
}
|
||||
if ($sigs) {
|
||||
foreach ($sigs as $sig) {
|
||||
$this->element('Type', null, $sig);
|
||||
}
|
||||
}
|
||||
if ($localId) {
|
||||
$this->element('LocalID', null, $localId);
|
||||
}
|
||||
$this->elementEnd('Service');
|
||||
}
|
||||
}
|
||||
|
173
plugins/OpenID/xrds.php
Normal file
173
plugins/OpenID/xrds.php
Normal file
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* XRDS for OpenID
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Action
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @author Robin Millette <millette@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://laconi.ca/
|
||||
*
|
||||
* Laconica - a distributed open-source microblogging tool
|
||||
* Copyright (C) 2008, 2009, Control Yourself, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (!defined('LACONICA')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once INSTALLDIR.'/lib/omb.php';
|
||||
|
||||
/**
|
||||
* XRDS for OpenID
|
||||
*
|
||||
* @category Action
|
||||
* @package Laconica
|
||||
* @author Evan Prodromou <evan@controlyourself.ca>
|
||||
* @author Robin Millette <millette@controlyourself.ca>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://laconi.ca/
|
||||
*/
|
||||
class XrdsAction extends Action
|
||||
{
|
||||
/**
|
||||
* Is read only?
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function isReadOnly($args)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class handler.
|
||||
*
|
||||
* @param array $args query arguments
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function handle($args)
|
||||
{
|
||||
parent::handle($args);
|
||||
$nickname = $this->trimmed('nickname');
|
||||
$user = User::staticGet('nickname', $nickname);
|
||||
if (!$user) {
|
||||
$this->clientError(_('No such user.'));
|
||||
return;
|
||||
}
|
||||
$this->showXrds($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show XRDS for a user.
|
||||
*
|
||||
* @param class $user XRDS for this user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showXrds($user)
|
||||
{
|
||||
header('Content-Type: application/xrds+xml');
|
||||
$this->startXML();
|
||||
$this->elementStart('XRDS', array('xmlns' => 'xri://$xrds'));
|
||||
|
||||
$this->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
|
||||
'xml:id' => 'oauth',
|
||||
'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
|
||||
'version' => '2.0'));
|
||||
$this->element('Type', null, 'xri://$xrds*simple');
|
||||
$this->showService(OAUTH_ENDPOINT_REQUEST,
|
||||
common_local_url('requesttoken'),
|
||||
array(OAUTH_AUTH_HEADER, OAUTH_POST_BODY),
|
||||
array(OAUTH_HMAC_SHA1),
|
||||
$user->uri);
|
||||
$this->showService(OAUTH_ENDPOINT_AUTHORIZE,
|
||||
common_local_url('userauthorization'),
|
||||
array(OAUTH_AUTH_HEADER, OAUTH_POST_BODY),
|
||||
array(OAUTH_HMAC_SHA1));
|
||||
$this->showService(OAUTH_ENDPOINT_ACCESS,
|
||||
common_local_url('accesstoken'),
|
||||
array(OAUTH_AUTH_HEADER, OAUTH_POST_BODY),
|
||||
array(OAUTH_HMAC_SHA1));
|
||||
$this->showService(OAUTH_ENDPOINT_RESOURCE,
|
||||
null,
|
||||
array(OAUTH_AUTH_HEADER, OAUTH_POST_BODY),
|
||||
array(OAUTH_HMAC_SHA1));
|
||||
$this->elementEnd('XRD');
|
||||
|
||||
// XXX: decide whether to include user's ID/nickname in postNotice URL
|
||||
$this->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
|
||||
'xml:id' => 'omb',
|
||||
'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
|
||||
'version' => '2.0'));
|
||||
$this->element('Type', null, 'xri://$xrds*simple');
|
||||
$this->showService(OMB_ENDPOINT_POSTNOTICE,
|
||||
common_local_url('postnotice'));
|
||||
$this->showService(OMB_ENDPOINT_UPDATEPROFILE,
|
||||
common_local_url('updateprofile'));
|
||||
$this->elementEnd('XRD');
|
||||
$this->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
|
||||
'version' => '2.0'));
|
||||
$this->element('Type', null, 'xri://$xrds*simple');
|
||||
$this->showService(OAUTH_DISCOVERY,
|
||||
'#oauth');
|
||||
$this->showService(OMB_NAMESPACE,
|
||||
'#omb');
|
||||
$this->elementEnd('XRD');
|
||||
$this->elementEnd('XRDS');
|
||||
$this->endXML();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show service.
|
||||
*
|
||||
* @param string $type XRDS type
|
||||
* @param string $uri URI
|
||||
* @param array $params type parameters, null by default
|
||||
* @param array $sigs type signatures, null by default
|
||||
* @param string $localId local ID, null by default
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function showService($type, $uri, $params=null, $sigs=null, $localId=null)
|
||||
{
|
||||
$this->elementStart('Service');
|
||||
if ($uri) {
|
||||
$this->element('URI', null, $uri);
|
||||
}
|
||||
$this->element('Type', null, $type);
|
||||
if ($params) {
|
||||
foreach ($params as $param) {
|
||||
$this->element('Type', null, $param);
|
||||
}
|
||||
}
|
||||
if ($sigs) {
|
||||
foreach ($sigs as $sig) {
|
||||
$this->element('Type', null, $sig);
|
||||
}
|
||||
}
|
||||
if ($localId) {
|
||||
$this->element('LocalID', null, $localId);
|
||||
}
|
||||
$this->elementEnd('Service');
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user