gnu-social/actions/userauthorization.php

357 lines
13 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Let the user authorize a remote subscription request
*
* 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';
require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
require_once INSTALLDIR.'/extlib/libomb/profile.php';
define('TIMESTAMP_THRESHOLD', 300);
class UserauthorizationAction extends Action
{
var $error;
var $params;
function handle($args)
{
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
/* Use a session token for CSRF protection. */
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
$srv = $this->getStoredParams();
$this->showForm($srv->getRemoteUser(), _('There was a problem ' .
'with your session token. Try again, ' .
'please.'));
return;
}
/* We've shown the form, now post user's choice. */
$this->sendAuthorization();
} else {
if (!common_logged_in()) {
/* Go log in, and then come back. */
common_set_returnto($_SERVER['REQUEST_URI']);
common_redirect(common_local_url('login'));
return;
}
$user = common_current_user();
$profile = $user->getProfile();
if (!$profile) {
common_log_db_error($user, 'SELECT', __FILE__);
$this->serverError(_('User without matching profile'));
return;
}
/* TODO: If no token is passed the user should get a prompt to enter
it according to OAuth Core 1.0. */
try {
$this->validateOmb();
$srv = new OMB_Service_Provider(
profile_to_omb_profile($user->uri, $profile),
omb_oauth_datastore());
$remote_user = $srv->handleUserAuth();
} catch (Exception $e) {
$this->clearParams();
$this->clientError($e->getMessage());
return;
}
$this->storeParams($srv);
$this->showForm($remote_user);
}
}
function showForm($params, $error=null)
{
$this->params = $params;
$this->error = $error;
$this->showPage();
}
function title()
{
return _('Authorize subscription');
}
function showPageNotice()
{
$this->element('p', null, _('Please check these details to make sure '.
'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;
$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', array('class' => 'profile'));
$this->elementStart('div', 'entity_profile vcard');
$this->elementStart('a', array('href' => $profile,
'class' => 'url'));
if ($avatar) {
$this->element('img', array('src' => $avatar,
'class' => 'photo avatar',
'width' => AVATAR_PROFILE_SIZE,
'height' => AVATAR_PROFILE_SIZE,
'alt' => $nickname));
}
$hasFN = ($fullname !== '') ? 'nickname' : 'fn nickname';
$this->elementStart('span', $hasFN);
$this->raw($nickname);
$this->elementEnd('span');
$this->elementEnd('a');
if (!is_null($fullname)) {
$this->elementStart('dl', 'entity_fn');
$this->elementStart('dd');
$this->elementStart('span', 'fn');
$this->raw($fullname);
$this->elementEnd('span');
$this->elementEnd('dd');
$this->elementEnd('dl');
}
if (!is_null($location)) {
$this->elementStart('dl', 'entity_location');
$this->element('dt', null, _('Location'));
$this->elementStart('dd', 'label');
$this->raw($location);
$this->elementEnd('dd');
$this->elementEnd('dl');
}
if (!is_null($homepage)) {
$this->elementStart('dl', 'entity_url');
$this->element('dt', null, _('URL'));
$this->elementStart('dd');
$this->elementStart('a', array('href' => $homepage,
'class' => 'url'));
$this->raw($homepage);
$this->elementEnd('a');
$this->elementEnd('dd');
$this->elementEnd('dl');
}
if (!is_null($bio)) {
$this->elementStart('dl', 'entity_note');
$this->element('dt', null, _('Note'));
$this->elementStart('dd', 'note');
$this->raw($bio);
$this->elementEnd('dd');
$this->elementEnd('dl');
}
if (!is_null($license)) {
$this->elementStart('dl', 'entity_license');
$this->element('dt', null, _('License'));
$this->elementStart('dd', 'license');
$this->element('a', array('href' => $license,
'class' => 'license'),
$license);
$this->elementEnd('dd');
$this->elementEnd('dl');
}
$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',
'action' => common_local_url(
'userauthorization')));
$this->hidden('token', common_session_token());
$this->submit('accept', _('Accept'), 'submit accept', null,
_('Subscribe to this user'));
$this->submit('reject', _('Reject'), 'submit reject', null,
_('Reject this subscription'));
$this->elementEnd('form');
$this->elementEnd('li');
$this->elementEnd('ul');
$this->elementEnd('div');
$this->elementEnd('div');
}
function sendAuthorization()
{
$srv = $this->getStoredParams();
if (is_null($srv)) {
$this->clientError(_('No authorization request!'));
return;
}
$accepted = $this->arg('accept');
try {
list($val, $token) = $srv->continueUserAuth($accepted);
} catch (Exception $e) {
$this->clientError($e->getMessage());
return;
}
if ($val !== false) {
common_redirect($val, 303);
} elseif ($accepted) {
$this->showAcceptMessage($token);
} else {
$this->showRejectMessage();
}
}
function showAcceptMessage($tok)
{
common_show_header(_('Subscription authorized'));
$this->element('p', null,
_('The subscription has been authorized, but no '.
'callback URL was passed. Check with the sites ' .
'instructions for details on how to authorize the ' .
'subscription. Your subscription token is:'));
$this->element('blockquote', 'token', $tok);
common_show_footer();
}
function showRejectMessage()
{
common_show_header(_('Subscription rejected'));
$this->element('p', null,
_('The subscription has been rejected, but no '.
'callback URL was passed. Check with the sites ' .
'instructions for details on how to fully reject ' .
'the subscription.'));
common_show_footer();
}
function storeParams($params)
{
common_ensure_session();
$_SESSION['userauthorizationparams'] = serialize($params);
}
function clearParams()
{
common_ensure_session();
unset($_SESSION['userauthorizationparams']);
}
function getStoredParams()
{
common_ensure_session();
$params = unserialize($_SESSION['userauthorizationparams']);
return $params;
}
function validateOmb()
{
$listener = $_GET['omb_listener'];
$listenee = $_GET['omb_listenee'];
$nickname = $_GET['omb_listenee_nickname'];
$profile = $_GET['omb_listenee_profile'];
$user = User::staticGet('uri', $listener);
if (!$user) {
throw new Exception(sprintf(_('Listener URI %s not found here'),
$listener));
}
if (strlen($listenee) > 255) {
throw new Exception(sprintf(_('Listenee URI %s is too long.'),
$listenee));
}
$other = User::staticGet('uri', $listenee);
if ($other) {
throw new Exception(sprintf(_('Listenee URI %s is a local user.'),
$listenee));
}
$remote = Remote_profile::staticGet('uri', $listenee);
if ($remote) {
$sub = new Subscription();
$sub->subscriber = $user->id;
$sub->subscribed = $remote->id;
if ($sub->find(true)) {
throw new Exception('You are already subscribed to this user.');
}
}
if ($profile == common_profile_url($nickname)) {
throw new Exception(sprintf(_('Profile URL %s is for a local user.'),
$profile));
}
$license = $_GET['omb_listenee_license'];
$site_license = common_config('license', 'url');
if (!common_compatible_license($license, $site_license)) {
throw new Exception(sprintf(_('Listenee stream license %s is not ' .
'compatible with site license %s.'),
$license, $site_license));
}
$avatar = $_GET['omb_listenee_avatar'];
if ($avatar) {
if (!common_valid_http_url($avatar) || strlen($avatar) > 255) {
throw new Exception(sprintf(_('Avatar URL %s is not valid.'),
$avatar));
}
$size = @getimagesize($avatar);
if (!$size) {
throw new Exception(sprintf(_('Cant read avatar URL %s.'),
$avatar));
}
if (!in_array($size[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG,
IMAGETYPE_PNG))) {
throw new Exception(sprintf(_('Wrong image type for avatar URL '.
'%s.'), $avatar));
}
}
}
}
?>