2010-02-09 06:37:45 +00:00
< ? php
/*
* StatusNet - the distributed open - source microblogging tool
2010-03-03 21:40:26 +00:00
* Copyright ( C ) 2009 - 2010 , StatusNet , Inc .
2010-02-09 06:37:45 +00:00
*
* 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 />.
*/
/**
* @ package OStatusPlugin
2010-02-20 20:46:48 +00:00
* @ maintainer Brion Vibber < brion @ status . net >
2010-02-09 06:37:45 +00:00
*/
2014-03-05 12:44:45 +00:00
if ( ! defined ( 'GNUSOCIAL' ) && ! defined ( 'STATUSNET' )) { exit ( 1 ); }
2010-02-09 06:37:45 +00:00
2010-02-23 01:58:05 +00:00
/**
* Key UI methods :
*
* showInputForm () - form asking for a remote profile account or URL
* We end up back here on errors
*
* showPreviewForm () - surrounding form for preview - and - confirm
2010-03-03 21:40:26 +00:00
* preview () - display profile for a remote user
2010-02-23 01:58:05 +00:00
*
2010-03-03 21:40:26 +00:00
* success () - redirects to subscriptions page on subscribe
2010-02-23 01:58:05 +00:00
*/
2010-02-09 06:37:45 +00:00
class OStatusSubAction extends Action
{
2010-02-23 01:58:05 +00:00
protected $profile_uri ; // provided acct: or URI of remote entity
protected $oprofile ; // Ostatus_profile of remote entity, if valid
2010-02-20 20:46:48 +00:00
2014-03-05 12:44:45 +00:00
protected function prepare ( array $args = array ())
{
parent :: prepare ( $args );
if ( ! common_logged_in ()) {
// XXX: selfURL() didn't work. :<
common_set_returnto ( $_SERVER [ 'REQUEST_URI' ]);
if ( Event :: handle ( 'RedirectToLogin' , array ( $this , null ))) {
common_redirect ( common_local_url ( 'login' ), 303 );
}
return false ;
}
if ( $this -> pullRemoteProfile ()) {
$this -> validateRemoteProfile ();
}
return true ;
}
/**
* Handle the submission .
*/
protected function handle ()
{
parent :: handle ();
if ( $_SERVER [ 'REQUEST_METHOD' ] == 'POST' ) {
$this -> handlePost ();
} else {
$this -> showForm ();
}
}
2010-02-20 20:46:48 +00:00
/**
2010-02-23 01:58:05 +00:00
* Show the initial form , when we haven ' t yet been given a valid
* remote profile .
2010-02-20 20:46:48 +00:00
*/
2010-02-23 01:58:05 +00:00
function showInputForm ()
2010-02-09 06:37:45 +00:00
{
$this -> elementStart ( 'form' , array ( 'method' => 'post' ,
2010-02-22 16:07:48 +00:00
'id' => 'form_ostatus_sub' ,
2010-02-09 06:37:45 +00:00
'class' => 'form_settings' ,
2010-03-03 21:40:26 +00:00
'action' => $this -> selfLink ()));
2010-02-09 06:37:45 +00:00
$this -> hidden ( 'token' , common_session_token ());
$this -> elementStart ( 'fieldset' , array ( 'id' => 'settings_feeds' ));
$this -> elementStart ( 'ul' , 'form_data' );
2010-02-13 17:46:10 +00:00
$this -> elementStart ( 'li' );
2010-02-20 20:46:48 +00:00
$this -> input ( 'profile' ,
2010-09-19 14:17:36 +01:00
// TRANS: Field label for a field that takes an OStatus user address.
2010-03-04 01:08:55 +00:00
_m ( 'Subscribe to' ),
2010-02-20 20:46:48 +00:00
$this -> profile_uri ,
2010-09-19 14:17:36 +01:00
// TRANS: Tooltip for field label "Subscribe to".
2011-04-29 17:59:47 +01:00
_m ( 'OStatus user\'s address, like nickname@example.com or http://example.net/nickname.' ));
2010-02-09 06:37:45 +00:00
$this -> elementEnd ( 'li' );
$this -> elementEnd ( 'ul' );
2010-09-19 14:17:36 +01:00
// TRANS: Button text.
$this -> submit ( 'validate' , _m ( 'BUTTON' , 'Continue' ));
2010-02-23 01:58:05 +00:00
$this -> elementEnd ( 'fieldset' );
$this -> elementEnd ( 'form' );
}
/**
* Show the preview - and - confirm form . We ' ve got a valid remote
* profile and are ready to poke it !
*
* This controls the wrapper form ; actual profile display will
* be in previewUser () or previewGroup () depending on the type .
*/
function showPreviewForm ()
{
2010-03-03 21:40:26 +00:00
$ok = $this -> preview ();
2010-02-23 19:56:17 +00:00
if ( ! $ok ) {
2011-06-05 10:30:46 +01:00
// @todo FIXME maybe provide a cancel button or link back?
2010-02-23 19:56:17 +00:00
return ;
2010-02-23 03:59:34 +00:00
}
$this -> elementStart ( 'div' , 'entity_actions' );
$this -> elementStart ( 'ul' );
$this -> elementStart ( 'li' , 'entity_subscribe' );
2010-02-23 01:58:05 +00:00
$this -> elementStart ( 'form' , array ( 'method' => 'post' ,
'id' => 'form_ostatus_sub' ,
2010-02-23 03:59:34 +00:00
'class' => 'form_remote_authorize' ,
2010-02-23 01:58:05 +00:00
'action' =>
2010-03-03 21:40:26 +00:00
$this -> selfLink ()));
2010-02-23 03:59:34 +00:00
$this -> elementStart ( 'fieldset' );
2010-02-23 01:58:05 +00:00
$this -> hidden ( 'token' , common_session_token ());
$this -> hidden ( 'profile' , $this -> profile_uri );
if ( $this -> oprofile -> isGroup ()) {
2011-04-29 17:59:47 +01:00
// TRANS: Button text.
2010-02-23 03:59:34 +00:00
$this -> submit ( 'submit' , _m ( 'Join' ), 'submit' , null ,
2010-09-19 14:17:36 +01:00
// TRANS: Tooltip for button "Join".
_m ( 'BUTTON' , 'Join this group' ));
2010-02-20 20:46:48 +00:00
} else {
2010-09-19 14:17:36 +01:00
// TRANS: Button text.
$this -> submit ( 'submit' , _m ( 'BUTTON' , 'Confirm' ), 'submit' , null ,
// TRANS: Tooltip for button "Confirm".
_m ( 'Subscribe to this user' ));
2010-02-20 20:46:48 +00:00
}
2010-02-09 06:37:45 +00:00
$this -> elementEnd ( 'fieldset' );
$this -> elementEnd ( 'form' );
2010-02-23 03:59:34 +00:00
$this -> elementEnd ( 'li' );
$this -> elementEnd ( 'ul' );
$this -> elementEnd ( 'div' );
2010-02-23 01:58:05 +00:00
}
/**
* Show a preview for a remote user ' s profile
2010-02-23 19:56:17 +00:00
* @ return boolean true if we ' re ok to try subscribing
2010-02-23 01:58:05 +00:00
*/
2010-03-03 21:40:26 +00:00
function preview ()
2010-02-23 01:58:05 +00:00
{
2014-05-19 17:07:38 +01:00
// Throws NoProfileException on localProfile when remote user's Profile not found
$profile = $this -> oprofile -> localProfile ();
2010-02-23 01:58:05 +00:00
2014-03-05 12:44:45 +00:00
if ( $this -> scoped -> isSubscribed ( $profile )) {
2010-02-23 19:56:17 +00:00
$this -> element ( 'div' , array ( 'class' => 'error' ),
2011-06-05 10:30:46 +01:00
// TRANS: Extra paragraph in remote profile view when already subscribed.
2011-04-29 17:59:47 +01:00
_m ( 'You are already subscribed to this user.' ));
2010-02-23 19:56:17 +00:00
$ok = false ;
} else {
$ok = true ;
}
2013-10-02 19:16:08 +01:00
$avatarUrl = $profile -> avatarUrl ( AVATAR_PROFILE_SIZE );
2010-02-23 19:37:49 +00:00
$this -> showEntity ( $profile ,
$profile -> profileurl ,
$avatarUrl ,
$profile -> bio );
2010-02-23 19:56:17 +00:00
return $ok ;
2010-02-23 01:58:05 +00:00
}
2010-02-23 19:37:49 +00:00
function showEntity ( $entity , $profile , $avatar , $note )
2010-02-23 03:59:34 +00:00
{
$nickname = $entity -> nickname ;
$fullname = $entity -> fullname ;
$homepage = $entity -> homepage ;
$location = $entity -> location ;
2010-03-16 16:25:18 +00:00
2010-02-23 03:59:34 +00:00
$this -> elementStart ( 'div' , 'entity_profile vcard' );
2010-02-23 19:37:49 +00:00
$this -> element ( 'img' , array ( 'src' => $avatar ,
2011-01-14 20:36:06 +00:00
'class' => 'photo avatar entity_depiction' ,
2010-02-23 19:37:49 +00:00
'width' => AVATAR_PROFILE_SIZE ,
'height' => AVATAR_PROFILE_SIZE ,
'alt' => $nickname ));
2010-02-23 03:59:34 +00:00
2011-01-14 20:36:06 +00:00
$hasFN = ( $fullname !== '' ) ? 'nickname' : 'fn nickname entity_nickname' ;
2010-02-23 03:59:34 +00:00
$this -> elementStart ( 'a' , array ( 'href' => $profile ,
'class' => 'url ' . $hasFN ));
2016-01-05 11:15:50 +00:00
$this -> text ( $nickname );
2010-02-23 03:59:34 +00:00
$this -> elementEnd ( 'a' );
if ( ! is_null ( $fullname )) {
2011-01-14 20:36:06 +00:00
$this -> elementStart ( 'div' , 'fn entity_fn' );
2016-01-05 11:15:50 +00:00
$this -> text ( $fullname );
2011-01-14 20:36:06 +00:00
$this -> elementEnd ( 'div' );
2010-02-23 03:59:34 +00:00
}
2011-01-14 20:36:06 +00:00
2010-02-23 03:59:34 +00:00
if ( ! is_null ( $location )) {
2011-01-14 20:36:06 +00:00
$this -> elementStart ( 'div' , 'label entity_location' );
2016-01-05 11:15:50 +00:00
$this -> text ( $location );
2011-01-14 20:36:06 +00:00
$this -> elementEnd ( 'div' );
2010-02-23 03:59:34 +00:00
}
if ( ! is_null ( $homepage )) {
$this -> elementStart ( 'a' , array ( 'href' => $homepage ,
2011-01-14 20:36:06 +00:00
'class' => 'url entity_url' ));
2016-01-05 11:15:50 +00:00
$this -> text ( $homepage );
2010-02-23 03:59:34 +00:00
$this -> elementEnd ( 'a' );
}
2010-02-23 19:37:49 +00:00
if ( ! is_null ( $note )) {
2011-01-14 20:36:06 +00:00
$this -> elementStart ( 'div' , 'note entity_note' );
2016-01-05 11:15:50 +00:00
$this -> text ( $note );
2011-01-14 20:36:06 +00:00
$this -> elementEnd ( 'div' );
2010-02-23 03:59:34 +00:00
}
$this -> elementEnd ( 'div' );
2010-02-23 01:58:05 +00:00
}
/**
* Redirect on successful remote user subscription
*/
2010-03-03 21:40:26 +00:00
function success ()
2010-02-23 01:58:05 +00:00
{
2014-03-05 12:44:45 +00:00
$url = common_local_url ( 'subscriptions' , array ( 'nickname' => $this -> scoped -> nickname ));
2010-02-23 01:58:05 +00:00
common_redirect ( $url , 303 );
}
/**
* Pull data for a remote profile and check if it ' s valid .
* Fills out error UI string in $this -> error
* Fills out $this -> oprofile on success .
*
* @ return boolean
*/
2010-03-03 21:40:26 +00:00
function pullRemoteProfile ()
2010-02-23 01:58:05 +00:00
{
2015-11-08 09:33:41 +00:00
$validate = new Validate ();
2017-04-19 10:37:43 +01:00
try {
$this -> profile_uri = Discovery :: normalize ( $this -> trimmed ( 'profile' ));
} catch ( Exception $e ) {
2017-04-19 10:41:34 +01:00
return false ;
2017-04-19 10:37:43 +01:00
}
2017-04-19 10:41:34 +01:00
2010-02-23 01:58:05 +00:00
try {
2017-04-16 10:01:16 +01:00
if ( Discovery :: isAcct ( $this -> profile_uri ) && $validate -> email ( mb_substr ( $this -> profile_uri , 5 ))) {
2010-02-23 21:11:44 +00:00
$this -> oprofile = Ostatus_profile :: ensureWebfinger ( $this -> profile_uri );
2015-11-08 22:24:20 +00:00
} else if ( $validate -> uri ( $this -> profile_uri )) {
2010-03-16 16:25:18 +00:00
$this -> oprofile = Ostatus_profile :: ensureProfileURL ( $this -> profile_uri );
2010-02-23 21:11:44 +00:00
} else {
2011-05-20 15:03:29 +01:00
// TRANS: Error message in OStatus plugin. Do not translate the domain names example.com
// TRANS: and example.net, as these are official standard domain names for use in examples.
2010-09-03 00:35:04 +01:00
$this -> error = _m ( " Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname. " );
2010-03-04 03:56:50 +00:00
common_debug ( 'Invalid address format.' , __FILE__ );
2010-02-23 21:11:44 +00:00
return false ;
}
2010-02-23 01:58:05 +00:00
return true ;
} catch ( FeedSubBadURLException $e ) {
2011-05-20 15:03:29 +01:00
// TRANS: Error message in OStatus plugin. Do not translate the domain names example.com
// TRANS: and example.net, as these are official standard domain names for use in examples.
2011-06-05 10:30:46 +01:00
$this -> error = _m ( 'Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname.' );
2010-03-04 03:56:50 +00:00
common_debug ( 'Invalid URL or could not reach server.' , __FILE__ );
2010-02-23 01:58:05 +00:00
} catch ( FeedSubBadResponseException $e ) {
2010-09-19 14:17:36 +01:00
// TRANS: Error text.
2011-06-05 10:30:46 +01:00
$this -> error = _m ( 'Sorry, we could not reach that feed. Please try that OStatus address again later.' );
2010-03-04 03:56:50 +00:00
common_debug ( 'Cannot read feed; server returned error.' , __FILE__ );
2010-02-23 01:58:05 +00:00
} catch ( FeedSubEmptyException $e ) {
2010-09-19 14:17:36 +01:00
// TRANS: Error text.
2011-06-05 10:30:46 +01:00
$this -> error = _m ( 'Sorry, we could not reach that feed. Please try that OStatus address again later.' );
2010-03-04 03:56:50 +00:00
common_debug ( 'Cannot read feed; server returned an empty page.' , __FILE__ );
2010-02-23 01:58:05 +00:00
} catch ( FeedSubBadHTMLException $e ) {
2010-09-19 14:17:36 +01:00
// TRANS: Error text.
2011-06-05 10:30:46 +01:00
$this -> error = _m ( 'Sorry, we could not reach that feed. Please try that OStatus address again later.' );
2010-03-04 03:56:50 +00:00
common_debug ( 'Bad HTML, could not find feed link.' , __FILE__ );
2010-02-23 01:58:05 +00:00
} catch ( FeedSubNoFeedException $e ) {
2010-09-19 14:17:36 +01:00
// TRANS: Error text.
2010-03-04 03:56:50 +00:00
$this -> error = _m ( " Sorry, we could not reach that feed. Please try that OStatus address again later. " );
common_debug ( 'Could not find a feed linked from this URL.' , __FILE__ );
2010-02-23 01:58:05 +00:00
} catch ( FeedSubUnrecognizedTypeException $e ) {
2010-09-19 14:17:36 +01:00
// TRANS: Error text.
2010-03-04 03:56:50 +00:00
$this -> error = _m ( " Sorry, we could not reach that feed. Please try that OStatus address again later. " );
common_debug ( 'Not a recognized feed type.' , __FILE__ );
2015-10-28 00:54:20 +00:00
} catch ( FeedSubNoHubException $e ) {
// TRANS: Error text.
$this -> error = _m ( " Sorry, that feed is not Pubsubhubub enabled. " );
common_debug ( 'No hub found.' , __FILE__ );
2010-03-04 02:23:28 +00:00
} catch ( Exception $e ) {
2010-02-23 01:58:05 +00:00
// Any new ones we forgot about
2011-05-20 15:03:29 +01:00
// TRANS: Error message in OStatus plugin. Do not translate the domain names example.com
// TRANS: and example.net, as these are official standard domain names for use in examples.
2010-09-03 00:35:04 +01:00
$this -> error = _m ( " Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname. " );
2010-03-04 03:56:50 +00:00
common_debug ( sprintf ( 'Bad feed URL: %s %s' , get_class ( $e ), $e -> getMessage ()), __FILE__ );
2010-02-23 01:58:05 +00:00
}
return false ;
}
2010-03-03 21:40:26 +00:00
function validateRemoteProfile ()
{
2011-03-06 19:15:34 +00:00
// Send us to the respective subscription form for conf
2010-03-03 21:40:26 +00:00
if ( $this -> oprofile -> isGroup ()) {
$target = common_local_url ( 'ostatusgroup' , array (), array ( 'profile' => $this -> profile_uri ));
common_redirect ( $target , 303 );
2011-03-06 19:15:34 +00:00
} else if ( $this -> oprofile -> isPeopletag ()) {
$target = common_local_url ( 'ostatuspeopletag' , array (), array ( 'profile' => $this -> profile_uri ));
common_redirect ( $target , 303 );
2010-03-03 21:40:26 +00:00
}
}
2010-02-23 01:58:05 +00:00
/**
* Attempt to finalize subscription .
* validateFeed must have been run first .
*
2010-03-03 21:40:26 +00:00
* Calls showForm on failure or success on success .
2010-02-23 01:58:05 +00:00
*/
function saveFeed ()
{
// And subscribe the current user to the local profile
2010-03-03 21:40:26 +00:00
$local = $this -> oprofile -> localProfile ();
2014-03-05 12:44:45 +00:00
if ( $this -> scoped -> isSubscribed ( $local )) {
2010-03-03 21:40:26 +00:00
// TRANS: OStatus remote subscription dialog error.
$this -> showForm ( _m ( 'Already subscribed!' ));
2014-03-05 12:44:45 +00:00
} elseif ( Subscription :: start ( $this -> scoped , $local )) {
2010-03-03 21:40:26 +00:00
$this -> success ();
2010-02-23 01:58:05 +00:00
} else {
2010-03-03 21:40:26 +00:00
// TRANS: OStatus remote subscription dialog error.
$this -> showForm ( _m ( 'Remote subscription failed!' ));
2010-02-20 20:46:48 +00:00
}
}
2010-02-09 06:37:45 +00:00
/**
* Handle posts to this form
*
* @ return void
*/
function handlePost ()
{
// CSRF protection
$token = $this -> trimmed ( 'token' );
if ( ! $token || $token != common_session_token ()) {
2011-04-10 23:39:27 +01:00
// TRANS: Client error displayed when the session token does not match or is not given.
2010-09-19 14:17:36 +01:00
$this -> showForm ( _m ( 'There was a problem with your session token. ' .
2010-02-09 06:37:45 +00:00
'Try again, please.' ));
return ;
}
2010-03-03 21:40:26 +00:00
if ( $this -> oprofile ) {
2010-02-23 19:37:49 +00:00
if ( $this -> arg ( 'submit' )) {
2010-02-23 01:58:05 +00:00
$this -> saveFeed ();
return ;
}
2010-02-09 06:37:45 +00:00
}
2010-02-23 01:58:05 +00:00
$this -> showForm ();
2010-02-09 06:37:45 +00:00
}
/**
2010-02-23 01:58:05 +00:00
* Show the appropriate form based on our input state .
2010-02-09 06:37:45 +00:00
*/
2010-02-23 01:58:05 +00:00
function showForm ( $err = null )
2010-02-09 06:37:45 +00:00
{
2010-02-23 01:58:05 +00:00
if ( $err ) {
$this -> error = $err ;
2010-02-09 06:37:45 +00:00
}
2010-02-23 01:58:05 +00:00
if ( $this -> boolean ( 'ajax' )) {
2013-09-24 00:17:04 +01:00
$this -> startHTML ( 'text/xml;charset=utf-8' );
2010-02-23 01:58:05 +00:00
$this -> elementStart ( 'head' );
2010-09-19 14:17:36 +01:00
// TRANS: Form title.
2010-02-23 01:58:05 +00:00
$this -> element ( 'title' , null , _m ( 'Subscribe to user' ));
$this -> elementEnd ( 'head' );
$this -> elementStart ( 'body' );
$this -> showContent ();
$this -> elementEnd ( 'body' );
2013-09-24 00:17:04 +01:00
$this -> endHTML ();
2010-02-23 01:58:05 +00:00
} else {
$this -> showPage ();
2010-02-09 06:37:45 +00:00
}
}
2010-02-23 01:58:05 +00:00
/**
* Title of the page
*
* @ return string Title of the page
*/
2010-02-09 06:37:45 +00:00
2010-02-23 01:58:05 +00:00
function title ()
{
2011-04-29 17:59:47 +01:00
// TRANS: Page title for OStatus remote subscription form.
2017-04-19 10:41:34 +01:00
return ! empty ( $this -> profile_uri ) ? _m ( 'Confirm' ) : _m ( 'Remote subscription' );
2010-02-23 01:58:05 +00:00
}
2010-02-20 20:46:48 +00:00
2010-02-23 01:58:05 +00:00
/**
* Instructions for use
*
* @ return instructions for use
*/
2010-02-20 20:46:48 +00:00
2010-02-23 01:58:05 +00:00
function getInstructions ()
{
2010-09-19 14:17:36 +01:00
// TRANS: Instructions.
2010-02-23 01:58:05 +00:00
return _m ( 'You can subscribe to users from other supported sites. Paste their address or profile URI below:' );
2010-02-09 06:37:45 +00:00
}
2010-02-23 01:58:05 +00:00
function showPageNotice ()
2010-02-09 06:37:45 +00:00
{
2010-02-23 19:37:49 +00:00
if ( ! empty ( $this -> error )) {
2010-02-23 01:58:05 +00:00
$this -> element ( 'p' , 'error' , $this -> error );
2010-02-09 06:37:45 +00:00
}
}
2010-02-23 01:58:05 +00:00
/**
* Content area of the page
*
* Shows a form for associating a remote OStatus account with this
* StatusNet account .
*
* @ return void
*/
function showContent ()
2010-02-20 20:46:48 +00:00
{
2010-02-23 01:58:05 +00:00
if ( $this -> oprofile ) {
$this -> showPreviewForm ();
} else {
$this -> showInputForm ();
}
2010-02-20 20:46:48 +00:00
}
2010-02-09 06:37:45 +00:00
2010-02-20 20:46:48 +00:00
function showScripts ()
{
parent :: showScripts ();
$this -> autofocus ( 'feedurl' );
}
2010-03-03 21:40:26 +00:00
function selfLink ()
{
return common_local_url ( 'ostatussub' );
}
2010-04-19 18:45:01 +01:00
/**
* Disable the send - notice form at the top of the page .
* This is really just a hack for the broken CSS in the Cloudy theme ,
* I think ; copying from other non - notice - navigation pages that do this
* as well . There will be plenty of others also broken .
*
* @ fixme fix the cloudy theme
* @ fixme do this in a more general way
*/
function showNoticeForm () {
// nop
}
2010-02-13 17:46:10 +00:00
}