gnu-social/actions/userauthorization.php

372 lines
14 KiB
PHP
Raw Normal View History

<?php
2009-08-10 13:48:50 +01:00
/**
* Let the user authorize a remote subscription request
*
* PHP version 5
*
* @category Action
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @author Robin Millette <millette@status.net>
2009-08-10 13:48:50 +01:00
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
2009-08-10 13:48:50 +01:00
*
2009-08-25 23:14:12 +01:00
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2008, 2009, StatusNet, 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('STATUSNET') && !defined('LACONICA')) { exit(1); }
2009-08-10 13:48:50 +01:00
require_once INSTALLDIR.'/lib/omb.php';
require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
require_once INSTALLDIR.'/extlib/libomb/profile.php';
define('TIMESTAMP_THRESHOLD', 300);
// @todo FIXME: Missing documentation.
class UserauthorizationAction extends Action
{
var $error;
var $params;
function handle($args)
{
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2009-08-10 13:48:50 +01:00
/* Use a session token for CSRF protection. */
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
2009-08-10 13:48:50 +01:00
$srv = $this->getStoredParams();
$this->showForm($srv->getRemoteUser(), _('There was a problem ' .
'with your session token. Try again, ' .
'please.'));
return;
}
2009-08-10 13:48:50 +01:00
/* We've shown the form, now post user's choice. */
$this->sendAuthorization();
} else {
if (!common_logged_in()) {
2009-08-10 13:48:50 +01:00
/* Go log in, and then come back. */
common_set_returnto($_SERVER['REQUEST_URI']);
common_redirect(common_local_url('login'));
return;
}
2009-08-10 13:48:50 +01:00
$user = common_current_user();
$profile = $user->getProfile();
if (!$profile) {
common_log_db_error($user, 'SELECT', __FILE__);
// TRANS: Server error displayed when trying to authorise a remote subscription request
// TRANS: while the user has no profile.
$this->serverError(_('User without matching profile.'));
2009-08-10 13:48:50 +01:00
return;
}
/* TODO: If no token is passed the user should get a prompt to enter
it according to OAuth Core 1.0. */
try {
2009-08-10 13:48:50 +01:00
$this->validateOmb();
$srv = new OMB_Service_Provider(
profile_to_omb_profile($user->uri, $profile),
2009-08-10 13:48:50 +01:00
omb_oauth_datastore());
$remote_user = $srv->handleUserAuth();
} catch (Exception $e) {
$this->clearParams();
$this->clientError($e->getMessage());
return;
}
2009-08-10 13:48:50 +01:00
$this->storeParams($srv);
$this->showForm($remote_user);
}
}
function showForm($params, $error=null)
{
$this->params = $params;
2009-08-10 13:48:50 +01:00
$this->error = $error;
$this->showPage();
}
function title()
{
// TRANS: Page title.
return _('Authorize subscription');
}
function showPageNotice()
{
// TRANS: Page notice on "Auhtorize subscription" page.
$this->element('p', null, _('Please check these details to make sure '.
2009-08-10 13:48:50 +01:00
'that you want to subscribe to this ' .
'users notices. If you didnt just ask ' .
'to subscribe to someones notices, '.
'click "Reject".'));
}
function showContent()
{
$params = $this->params;
2009-08-10 13:48:50 +01:00
$nickname = $params->getNickname();
$profile = $params->getProfileURL();
$license = $params->getLicenseURL();
$fullname = $params->getFullname();
$homepage = $params->getHomepage();
$bio = $params->getBio();
$location = $params->getLocation();
$avatar = $params->getAvatarURL();
$this->elementStart('div', 'entity_profile vcard');
2011-01-14 20:36:06 +00:00
if ($avatar) {
$this->element('img', array('src' => $avatar,
2011-01-14 20:36:06 +00:00
'class' => 'photo avatar entity_depiction',
'width' => AVATAR_PROFILE_SIZE,
'height' => AVATAR_PROFILE_SIZE,
'alt' => $nickname));
}
// TRANS: Label for nickname on user authorisation page.
2011-01-14 20:36:06 +00:00
$this->element('div', 'entity_nickname', _('Nickname'));
$hasFN = ($fullname !== '') ? 'nickname' : 'fn nickname';
2011-01-14 20:36:06 +00:00
// XXX: why are these raw() instead of escaped...?
$this->elementStart('a', array('href' => $profile,
'class' => 'url '.$hasFN));
$this->raw($nickname);
$this->elementEnd('a');
if (!is_null($fullname)) {
2011-01-14 20:36:06 +00:00
$this->elementStart('div', 'fn entity_fn');
$this->raw($fullname);
2011-01-14 20:36:06 +00:00
$this->elementEnd('div');
}
2011-01-14 20:36:06 +00:00
if (!is_null($location)) {
2011-01-14 20:36:06 +00:00
$this->elementStart('div', 'label entity_location');
$this->raw($location);
}
if (!is_null($homepage)) {
$this->elementStart('a', array('href' => $homepage,
2011-01-14 20:36:06 +00:00
'class' => 'url entity_url'));
$this->raw($homepage);
$this->elementEnd('a');
}
if (!is_null($bio)) {
2011-01-14 20:36:06 +00:00
$this->elementStart('div', 'note entity_note');
$this->raw($bio);
$this->elementEnd('dd');
}
if (!is_null($license)) {
$this->element('a', array('href' => $license,
2011-01-14 20:36:06 +00:00
'class' => 'license entity_license'),
$license);
}
2011-01-14 20:36:06 +00:00
$this->elementEnd('div');
$this->elementStart('div', 'entity_actions');
$this->elementStart('ul');
$this->elementStart('li', 'entity_subscribe');
$this->elementStart('form', array('method' => 'post',
'id' => 'userauthorization',
'class' => 'form_user_authorization',
'name' => 'userauthorization',
2009-08-10 13:48:50 +01:00
'action' => common_local_url(
'userauthorization')));
$this->hidden('token', common_session_token());
$this->submit('accept',
// TRANS: Button text on Authorise Subscription page.
_m('BUTTON','Accept'), 'submit accept', null,
// TRANS: Title for button on Authorise Subscription page.
_('Subscribe to this user.'));
$this->submit('reject',
// TRANS: Button text on Authorise Subscription page.
_m('BUTTON','Reject'), 'submit reject', null,
// TRANS: Title for button on Authorise Subscription page.
_('Reject this subscription.'));
$this->elementEnd('form');
$this->elementEnd('li');
$this->elementEnd('ul');
$this->elementEnd('div');
}
function sendAuthorization()
{
2009-08-10 13:48:50 +01:00
$srv = $this->getStoredParams();
2009-08-10 13:48:50 +01:00
if (is_null($srv)) {
// TRANS: Client error displayed for an empty authorisation request.
$this->clientError(_('No authorization request!'));
return;
}
2009-08-10 13:48:50 +01:00
$accepted = $this->arg('accept');
try {
list($val, $token) = $srv->continueUserAuth($accepted);
} catch (Exception $e) {
$this->clientError($e->getMessage());
return;
}
2009-08-10 13:48:50 +01:00
if ($val !== false) {
common_redirect($val, 303);
} elseif ($accepted) {
$this->showAcceptMessage($token);
} else {
2009-08-10 13:48:50 +01:00
$this->showRejectMessage();
}
}
function showAcceptMessage($tok)
{
// TRANS: Accept message header from Authorise subscription page.
common_show_header(_('Subscription authorized'));
// TRANS: Accept message text from Authorise subscription page.
$this->element('p', null,
_('The subscription has been authorized, but no '.
'callback URL was passed. Check with the sites ' .
2009-08-10 13:48:50 +01:00
'instructions for details on how to authorize the ' .
'subscription. Your subscription token is:'));
$this->element('blockquote', 'token', $tok);
common_show_footer();
}
2009-08-10 13:48:50 +01:00
function showRejectMessage()
{
// TRANS: Reject message header from Authorise subscription page.
common_show_header(_('Subscription rejected'));
// TRANS: Reject message from Authorise subscription page.
$this->element('p', null,
_('The subscription has been rejected, but no '.
'callback URL was passed. Check with the sites ' .
2009-08-10 13:48:50 +01:00
'instructions for details on how to fully reject ' .
'the subscription.'));
common_show_footer();
}
function storeParams($params)
{
common_ensure_session();
2009-08-10 13:48:50 +01:00
$_SESSION['userauthorizationparams'] = serialize($params);
}
function clearParams()
{
common_ensure_session();
unset($_SESSION['userauthorizationparams']);
}
function getStoredParams()
{
common_ensure_session();
2009-08-10 13:48:50 +01:00
$params = unserialize($_SESSION['userauthorizationparams']);
return $params;
}
function validateOmb()
{
$listener = $_GET['omb_listener'];
2009-08-10 13:48:50 +01:00
$listenee = $_GET['omb_listenee'];
$nickname = $_GET['omb_listenee_nickname'];
$profile = $_GET['omb_listenee_profile'];
$user = User::staticGet('uri', $listener);
if (!$user) {
// TRANS: Exception thrown when no valid user is found for an authorisation request.
// TRANS: %s is a listener URI.
throw new Exception(sprintf(_('Listener URI "%s" not found here.'),
$listener));
}
if (strlen($listenee) > 255) {
// TRANS: Exception thrown when listenee URI is too long for an authorisation request.
// TRANS: %s is a listenee URI.
throw new Exception(sprintf(_('Listenee URI "%s" is too long.'),
$listenee));
}
$other = User::staticGet('uri', $listenee);
if ($other) {
// TRANS: Exception thrown when listenee URI is a local user for an authorisation request.
// TRANS: %s is a listenee URI.
throw new Exception(sprintf(_('Listenee URI "%s" is a local user.'),
$listenee));
}
$remote = Remote_profile::staticGet('uri', $listenee);
if ($remote) {
2009-08-10 13:48:50 +01:00
$sub = new Subscription();
$sub->subscriber = $user->id;
$sub->subscribed = $remote->id;
if ($sub->find(true)) {
// TRANS: Exception thrown when already subscribed.
2009-08-10 13:48:50 +01:00
throw new Exception('You are already subscribed to this user.');
}
}
2009-08-10 13:48:50 +01:00
if ($profile == common_profile_url($nickname)) {
// TRANS: Exception thrown when profile URL is a local user for an authorisation request.
// TRANS: %s is a profile URL.
throw new Exception(sprintf(_('Profile URL "%s" is for a local user.'),
$profile));
}
2009-08-10 13:48:50 +01:00
$license = $_GET['omb_listenee_license'];
$site_license = common_config('license', 'url');
if (!common_compatible_license($license, $site_license)) {
// TRANS: Exception thrown when licenses are not compatible for an authorisation request.
// TRANS: %1$s is the license for the listenee, %2$s is the license for "this" StatusNet site.
throw new Exception(sprintf(_('Listenee stream license "%1$s" is not ' .
'compatible with site license "%2$s".'),
$license, $site_license));
}
$avatar = $_GET['omb_listenee_avatar'];
if ($avatar) {
if (!common_valid_http_url($avatar) || strlen($avatar) > 255) {
// TRANS: Exception thrown when avatar URL is invalid for an authorisation request.
// TRANS: %s is an avatar URL.
throw new Exception(sprintf(_('Avatar URL "%s" is not valid.'),
$avatar));
}
$size = @getimagesize($avatar);
if (!$size) {
// TRANS: Exception thrown when avatar URL could not be read for an authorisation request.
// TRANS: %s is an avatar URL.
throw new Exception(sprintf(_('Cannot read avatar URL "%s".'),
$avatar));
}
if (!in_array($size[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG,
IMAGETYPE_PNG))) {
// TRANS: Exception thrown when avatar URL return an invalid image type for an authorisation request.
// TRANS: %s is an avatar URL.
throw new Exception(sprintf(_('Wrong image type for avatar URL '.
'"%s".'), $avatar));
}
}
}
}