summaryrefslogtreecommitdiff
path: root/actions
diff options
context:
space:
mode:
Diffstat (limited to 'actions')
-rw-r--r--actions/accesstoken.php28
-rw-r--r--actions/all.php34
-rw-r--r--actions/allrss.php4
-rw-r--r--actions/api.php5
-rw-r--r--actions/attachment.php12
-rw-r--r--actions/avatarsettings.php17
-rw-r--r--actions/confirmaddress.php6
-rw-r--r--actions/editgroup.php4
-rw-r--r--actions/emailsettings.php14
-rw-r--r--actions/favorited.php3
-rw-r--r--actions/favoritesrss.php4
-rw-r--r--actions/finishremotesubscribe.php317
-rw-r--r--actions/grouplogo.php17
-rw-r--r--actions/grouprss.php5
-rw-r--r--actions/groupsearch.php3
-rw-r--r--actions/imsettings.php6
-rw-r--r--actions/invite.php2
-rw-r--r--actions/login.php2
-rw-r--r--actions/newgroup.php4
-rw-r--r--actions/newmessage.php7
-rw-r--r--actions/newnotice.php68
-rw-r--r--actions/noticesearch.php4
-rw-r--r--actions/noticesearchrss.php5
-rw-r--r--actions/oembed.php (renamed from actions/twitapioembed.php)61
-rw-r--r--actions/opensearch.php2
-rw-r--r--actions/postnotice.php113
-rw-r--r--actions/profilesettings.php16
-rw-r--r--actions/public.php34
-rw-r--r--actions/publicrss.php4
-rw-r--r--actions/publictagcloud.php3
-rw-r--r--actions/register.php15
-rw-r--r--actions/remotesubscribe.php340
-rw-r--r--actions/replies.php17
-rw-r--r--actions/repliesrss.php3
-rw-r--r--actions/requesttoken.php21
-rw-r--r--actions/showfavorites.php48
-rw-r--r--actions/showgroup.php19
-rw-r--r--actions/shownotice.php18
-rw-r--r--actions/showstream.php10
-rw-r--r--actions/smssettings.php6
-rw-r--r--actions/subscribers.php4
-rw-r--r--actions/subscriptions.php16
-rw-r--r--actions/tag.php13
-rw-r--r--actions/tagrss.php3
-rw-r--r--actions/twitapidirect_messages.php7
-rw-r--r--actions/twitapigroups.php97
-rw-r--r--actions/twitapistatuses.php23
-rw-r--r--actions/twitterauthorization.php222
-rw-r--r--actions/twittersettings.php389
-rw-r--r--actions/unsubscribe.php41
-rw-r--r--actions/updateprofile.php163
-rw-r--r--actions/userauthorization.php423
-rw-r--r--actions/userrss.php5
-rw-r--r--actions/xrds.php104
54 files changed, 1194 insertions, 1617 deletions
diff --git a/actions/accesstoken.php b/actions/accesstoken.php
index 2a8cd1713..dcd04a1b4 100644
--- a/actions/accesstoken.php
+++ b/actions/accesstoken.php
@@ -1,6 +1,6 @@
<?php
/**
- * Access token class.
+ * Access token class
*
* PHP version 5
*
@@ -32,10 +32,11 @@ if (!defined('LACONICA')) {
exit(1);
}
+require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
require_once INSTALLDIR.'/lib/omb.php';
/**
- * Access token class.
+ * Access token class
*
* @category Action
* @package Laconica
@@ -47,28 +48,23 @@ require_once INSTALLDIR.'/lib/omb.php';
class AccesstokenAction extends Action
{
/**
- * Class handler.
+ * Class handler
*
* @param array $args query arguments
*
- * @return boolean false if user doesn't exist
- */
+ * @return nothing
+ *
+ **/
function handle($args)
{
parent::handle($args);
try {
- common_debug('getting request from env variables', __FILE__);
- common_remove_magic_from_request();
- $req = OAuthRequest::from_request('POST', common_local_url('accesstoken'));
- common_debug('getting a server', __FILE__);
- $server = omb_oauth_server();
- common_debug('fetching the access token', __FILE__);
- $token = $server->fetch_access_token($req);
- common_debug('got this token: "'.print_r($token, true).'"', __FILE__);
- common_debug('printing the access token', __FILE__);
- print $token;
- } catch (OAuthException $e) {
+ $srv = new OMB_Service_Provider(null, omb_oauth_datastore(),
+ omb_oauth_server());
+ $srv->writeAccessToken();
+ } catch (Exception $e) {
$this->serverError($e->getMessage());
}
}
}
+?>
diff --git a/actions/all.php b/actions/all.php
index f06ead2a8..38aee65b6 100644
--- a/actions/all.php
+++ b/actions/all.php
@@ -25,11 +25,31 @@ require_once INSTALLDIR.'/lib/feedlist.php';
class AllAction extends ProfileAction
{
+ var $notice;
+
function isReadOnly($args)
{
return true;
}
+ function prepare($args)
+ {
+ parent::prepare($args);
+ $cur = common_current_user();
+
+ if (!empty($cur) && $cur->id == $this->user->id) {
+ $this->notice = $this->user->noticeInbox(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
+ } else {
+ $this->notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
+ }
+
+ if($this->page > 1 && $this->notice->N == 0){
+ $this->serverError(_('No such page'),$code=404);
+ }
+
+ return true;
+ }
+
function handle($args)
{
parent::handle($args);
@@ -88,7 +108,9 @@ class AllAction extends ProfileAction
}
}
else {
- $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname);
+ $message .= sprintf(_('Why not [register an account](%%%%action.%s%%%%) and then nudge %s or post a notice to his or her attention.'),
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin',
+ $this->user->nickname);
}
$this->elementStart('div', 'guide');
@@ -98,15 +120,7 @@ class AllAction extends ProfileAction
function showContent()
{
- $cur = common_current_user();
-
- if (!empty($cur) && $cur->id == $this->user->id) {
- $notice = $this->user->noticeInbox(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
- } else {
- $notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
- }
-
- $nl = new NoticeList($notice, $this);
+ $nl = new NoticeList($this->notice, $this);
$cnt = $nl->show();
diff --git a/actions/allrss.php b/actions/allrss.php
index 885a67f61..260667090 100644
--- a/actions/allrss.php
+++ b/actions/allrss.php
@@ -115,8 +115,8 @@ class AllrssAction extends Rss10Action
'link' => common_local_url('all',
array('nickname' =>
$user->nickname)),
- 'description' => sprintf(_('Feed for friends of %s'),
- $user->nickname));
+ 'description' => sprintf(_('Updates from %1$s and friends on %2$s!'),
+ $user->nickname, common_config('site', 'name')));
return $c;
}
diff --git a/actions/api.php b/actions/api.php
index 99ab262ad..6d226af7e 100644
--- a/actions/api.php
+++ b/actions/api.php
@@ -131,6 +131,8 @@ class ApiAction extends Action
'tags/timeline',
'oembed/oembed',
'groups/show',
+ 'groups/timeline',
+ 'groups/list_all',
'groups/timeline');
static $bareauth = array('statuses/user_timeline',
@@ -140,7 +142,8 @@ class ApiAction extends Action
'statuses/mentions',
'statuses/followers',
'favorites/favorites',
- 'friendships/show');
+ 'friendships/show',
+ 'groups/list_groups');
$fullname = "$this->api_action/$this->api_method";
diff --git a/actions/attachment.php b/actions/attachment.php
index c6a5d0d52..f42906fd8 100644
--- a/actions/attachment.php
+++ b/actions/attachment.php
@@ -103,18 +103,18 @@ class AttachmentAction extends Action
$this->element('link',array('rel'=>'alternate',
'type'=>'application/json+oembed',
'href'=>common_local_url(
- 'api',
- array('apiaction'=>'oembed','method'=>'oembed.json'),
- array('url'=>
+ 'oembed',
+ array(),
+ array('format'=>'json', 'url'=>
common_local_url('attachment',
array('attachment' => $this->attachment->id)))),
'title'=>'oEmbed'),null);
$this->element('link',array('rel'=>'alternate',
'type'=>'text/xml+oembed',
'href'=>common_local_url(
- 'api',
- array('apiaction'=>'oembed','method'=>'oembed.xml'),
- array('url'=>
+ 'oembed',
+ array(),
+ array('format'=>'xml','url'=>
common_local_url('attachment',
array('attachment' => $this->attachment->id)))),
'title'=>'oEmbed'),null);
diff --git a/actions/avatarsettings.php b/actions/avatarsettings.php
index c2bb35a39..c45514ff6 100644
--- a/actions/avatarsettings.php
+++ b/actions/avatarsettings.php
@@ -382,13 +382,7 @@ class AvatarsettingsAction extends AccountSettingsAction
function showStylesheets()
{
parent::showStylesheets();
- $jcropStyle =
- common_path('theme/base/css/jquery.Jcrop.css?version='.LACONICA_VERSION);
-
- $this->element('link', array('rel' => 'stylesheet',
- 'type' => 'text/css',
- 'href' => $jcropStyle,
- 'media' => 'screen, projection, tv'));
+ $this->cssLink('css/jquery.Jcrop.css','base','screen, projection, tv');
}
/**
@@ -402,13 +396,8 @@ class AvatarsettingsAction extends AccountSettingsAction
parent::showScripts();
if ($this->mode == 'crop') {
- $jcropPack = common_path('js/jcrop/jquery.Jcrop.pack.js');
- $jcropGo = common_path('js/jcrop/jquery.Jcrop.go.js');
-
- $this->element('script', array('type' => 'text/javascript',
- 'src' => $jcropPack));
- $this->element('script', array('type' => 'text/javascript',
- 'src' => $jcropGo));
+ $this->script('js/jcrop/jquery.Jcrop.min.js');
+ $this->script('js/jcrop/jquery.Jcrop.go.js');
}
}
}
diff --git a/actions/confirmaddress.php b/actions/confirmaddress.php
index 725c1f1e3..3c41a5c70 100644
--- a/actions/confirmaddress.php
+++ b/actions/confirmaddress.php
@@ -67,7 +67,11 @@ class ConfirmaddressAction extends Action
parent::handle($args);
if (!common_logged_in()) {
common_set_returnto($this->selfUrl());
- common_redirect(common_local_url('login'));
+ if (!common_config('site', 'openidonly')) {
+ common_redirect(common_local_url('login'));
+ } else {
+ common_redirect(common_local_url('openidlogin'));
+ }
return;
}
$code = $this->trimmed('code');
diff --git a/actions/editgroup.php b/actions/editgroup.php
index 6aa6f8b11..aeeea2b63 100644
--- a/actions/editgroup.php
+++ b/actions/editgroup.php
@@ -196,8 +196,8 @@ class EditgroupAction extends GroupDesignAction
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
$this->showForm(_('Full name is too long (max 255 chars).'));
return;
- } else if (!is_null($description) && mb_strlen($description) > 140) {
- $this->showForm(_('description is too long (max 140 chars).'));
+ } else if (User_group::descriptionTooLong($description)) {
+ $this->showForm(sprintf(_('description is too long (max %d chars).'), User_group::maxDescription()));
return;
} else if (!is_null($location) && mb_strlen($location) > 255) {
$this->showForm(_('Location is too long (max 255 chars).'));
diff --git a/actions/emailsettings.php b/actions/emailsettings.php
index 634388fdd..cdd092829 100644
--- a/actions/emailsettings.php
+++ b/actions/emailsettings.php
@@ -122,7 +122,7 @@ class EmailsettingsAction extends AccountSettingsAction
}
$this->elementEnd('fieldset');
- if ($user->email) {
+ if (common_config('emailpost', 'enabled') && $user->email) {
$this->elementStart('fieldset', array('id' => 'settings_email_incoming'));
$this->element('legend',_('Incoming email'));
if ($user->incomingemail) {
@@ -173,11 +173,13 @@ class EmailsettingsAction extends AccountSettingsAction
_('Allow friends to nudge me and send me an email.'),
$user->emailnotifynudge);
$this->elementEnd('li');
- $this->elementStart('li');
- $this->checkbox('emailpost',
- _('I want to post notices by email.'),
- $user->emailpost);
- $this->elementEnd('li');
+ if (common_config('emailpost', 'enabled')) {
+ $this->elementStart('li');
+ $this->checkbox('emailpost',
+ _('I want to post notices by email.'),
+ $user->emailpost);
+ $this->elementEnd('li');
+ }
$this->elementStart('li');
$this->checkbox('emailmicroid',
_('Publish a MicroID for my email address.'),
diff --git a/actions/favorited.php b/actions/favorited.php
index 156c7a700..a3d1a5e20 100644
--- a/actions/favorited.php
+++ b/actions/favorited.php
@@ -153,7 +153,8 @@ class FavoritedAction extends Action
$message .= _('Be the first to add a notice to your favorites by clicking the fave button next to any notice you like.');
}
else {
- $message .= _('Why not [register an account](%%action.register%%) and be the first to add a notice to your favorites!');
+ $message .= sprintf(_('Why not [register an account](%%%%action.%s%%%%) and be the first to add a notice to your favorites!'),
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin');
}
$this->elementStart('div', 'guide');
diff --git a/actions/favoritesrss.php b/actions/favoritesrss.php
index c439a9a62..5dc09e5e8 100644
--- a/actions/favoritesrss.php
+++ b/actions/favoritesrss.php
@@ -111,8 +111,8 @@ class FavoritesrssAction extends Rss10Action
'link' => common_local_url('showfavorites',
array('nickname' =>
$user->nickname)),
- 'description' => sprintf(_('Feed of favorite notices of %s'),
- $user->nickname));
+ 'description' => sprintf(_('Updates favored by %1$s on %2$s!'),
+ $user->nickname, common_config('site', 'name')));
return $c;
}
diff --git a/actions/finishremotesubscribe.php b/actions/finishremotesubscribe.php
index 5c764aeb0..da563cb29 100644
--- a/actions/finishremotesubscribe.php
+++ b/actions/finishremotesubscribe.php
@@ -1,5 +1,16 @@
<?php
-/*
+/**
+ * Handler for remote subscription finish callback
+ *
+ * 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.
*
@@ -15,285 +26,123 @@
*
* 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); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
-require_once(INSTALLDIR.'/lib/omb.php');
+require_once INSTALLDIR.'/extlib/libomb/service_consumer.php';
+require_once INSTALLDIR.'/lib/omb.php';
+/**
+ * Handler for remote subscription finish callback
+ *
+ * When a remote user subscribes a local user, a redirect to this action is
+ * issued after the remote user authorized his service to subscribe.
+ *
+ * @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 FinishremotesubscribeAction extends Action
{
+ /**
+ * Class handler.
+ *
+ * @param array $args query arguments
+ *
+ * @return nothing
+ *
+ **/
function handle($args)
{
-
parent::handle($args);
- if (common_logged_in()) {
- $this->clientError(_('You can use the local subscription!'));
- return;
- }
-
- $omb = $_SESSION['oauth_authorization_request'];
+ /* Restore session data. RemotesubscribeAction should have stored
+ this entry. */
+ $service = unserialize($_SESSION['oauth_authorization_request']);
- if (!$omb) {
+ if (!$service) {
$this->clientError(_('Not expecting this response!'));
return;
}
- common_debug('stored request: '.print_r($omb,true), __FILE__);
-
- common_remove_magic_from_request();
- $req = OAuthRequest::from_request('POST', common_local_url('finishuserauthorization'));
-
- $token = $req->get_parameter('oauth_token');
-
- # I think this is the success metric
-
- if ($token != $omb['token']) {
- $this->clientError(_('Not authorized.'));
- return;
- }
-
- $version = $req->get_parameter('omb_version');
-
- if ($version != OMB_VERSION_01) {
- $this->clientError(_('Unknown version of OMB protocol.'));
- return;
- }
-
- $nickname = $req->get_parameter('omb_listener_nickname');
-
- if (!$nickname) {
- $this->clientError(_('No nickname provided by remote server.'));
- return;
- }
-
- $profile_url = $req->get_parameter('omb_listener_profile');
-
- if (!$profile_url) {
- $this->clientError(_('No profile URL returned by server.'));
- return;
- }
-
- if (!Validate::uri($profile_url, array('allowed_schemes' => array('http', 'https')))) {
- $this->clientError(_('Invalid profile URL returned by server.'));
- return;
- }
-
- if ($profile_url == common_local_url('showstream', array('nickname' => $nickname))) {
- $this->clientError(_('You can use the local subscription!'));
- return;
- }
-
- common_debug('listenee: "'.$omb['listenee'].'"', __FILE__);
+ common_debug('stored request: '. print_r($service, true), __FILE__);
- $user = User::staticGet('nickname', $omb['listenee']);
+ /* Create user objects for both users. Do it early for request
+ validation. */
+ $user = User::staticGet('uri', $service->getListeneeURI());
if (!$user) {
- $this->clientError(_('User being listened to doesn\'t exist.'));
+ $this->clientError(_('User being listened to does not exist.'));
return;
}
- $other = User::staticGet('uri', $omb['listener']);
+ $other = User::staticGet('uri', $service->getListenerURI());
if ($other) {
$this->clientError(_('You can use the local subscription!'));
return;
}
- $fullname = $req->get_parameter('omb_listener_fullname');
- $homepage = $req->get_parameter('omb_listener_homepage');
- $bio = $req->get_parameter('omb_listener_bio');
- $location = $req->get_parameter('omb_listener_location');
- $avatar_url = $req->get_parameter('omb_listener_avatar');
+ $remote = Remote_profile::staticGet('uri', $service->getListenerURI());
- list($newtok, $newsecret) = $this->access_token($omb);
+ $profile = Profile::staticGet($remote->id);
- if (!$newtok || !$newsecret) {
- $this->clientError(_('Couldn\'t convert request tokens to access tokens.'));
+ if ($user->hasBlocked($profile)) {
+ $this->clientError(_('That user has blocked you from subscribing.'));
return;
}
- # XXX: possible attack point; subscribe and return someone else's profile URI
-
- $remote = Remote_profile::staticGet('uri', $omb['listener']);
-
- if ($remote) {
- $exists = true;
- $profile = Profile::staticGet($remote->id);
- $orig_remote = clone($remote);
- $orig_profile = clone($profile);
- # XXX: compare current postNotice and updateProfile URLs to the ones
- # stored in the DB to avoid (possibly...) above attack
- } else {
- $exists = false;
- $remote = new Remote_profile();
- $remote->uri = $omb['listener'];
- $profile = new Profile();
- }
-
- $profile->nickname = $nickname;
- $profile->profileurl = $profile_url;
-
- if (!is_null($fullname)) {
- $profile->fullname = $fullname;
- }
- if (!is_null($homepage)) {
- $profile->homepage = $homepage;
- }
- if (!is_null($bio)) {
- $profile->bio = $bio;
- }
- if (!is_null($location)) {
- $profile->location = $location;
- }
-
- if ($exists) {
- $profile->update($orig_profile);
- } else {
- $profile->created = DB_DataObject_Cast::dateTime(); # current time
- $id = $profile->insert();
- if (!$id) {
- $this->serverError(_('Error inserting new profile'));
- return;
- }
- $remote->id = $id;
- }
-
- if ($avatar_url) {
- if (!$this->add_avatar($profile, $avatar_url)) {
- $this->serverError(_('Error inserting avatar'));
+ /* Perform the handling itself via libomb. */
+ try {
+ $service->finishAuthorization();
+ } catch (OAuthException $e) {
+ if ($e->getMessage() == 'The authorized token does not equal the ' .
+ 'submitted token.') {
+ $this->clientError(_('You are not authorized.'));
return;
- }
- }
-
- $remote->postnoticeurl = $omb['post_notice_url'];
- $remote->updateprofileurl = $omb['update_profile_url'];
-
- if ($exists) {
- if (!$remote->update($orig_remote)) {
- $this->serverError(_('Error updating remote profile'));
- return;
- }
- } else {
- $remote->created = DB_DataObject_Cast::dateTime(); # current time
- if (!$remote->insert()) {
- $this->serverError(_('Error inserting remote profile'));
+ } else {
+ $this->clientError(_('Could not convert request token to ' .
+ 'access token.'));
return;
}
- }
-
- if ($user->hasBlocked($profile)) {
- $this->clientError(_('That user has blocked you from subscribing.'));
+ } catch (OMB_RemoteServiceException $e) {
+ $this->clientError(_('Remote service uses unknown version of ' .
+ 'OMB protocol.'));
+ return;
+ } catch (Exception $e) {
+ common_debug('Got exception ' . print_r($e, true), __FILE__);
+ $this->clientError($e->getMessage());
return;
}
- $sub = new Subscription();
+ /* The service URLs are not accessible from datastore, so setting them
+ after insertion of the profile. */
+ $orig_remote = clone($remote);
- $sub->subscriber = $remote->id;
- $sub->subscribed = $user->id;
+ $remote->postnoticeurl =
+ $service->getServiceURI(OMB_ENDPOINT_POSTNOTICE);
+ $remote->updateprofileurl =
+ $service->getServiceURI(OMB_ENDPOINT_UPDATEPROFILE);
- $sub_exists = false;
-
- if ($sub->find(true)) {
- $sub_exists = true;
- $orig_sub = clone($sub);
- } else {
- $sub_exists = false;
- $sub->created = DB_DataObject_Cast::dateTime(); # current time
- }
-
- $sub->token = $newtok;
- $sub->secret = $newsecret;
-
- if ($sub_exists) {
- $result = $sub->update($orig_sub);
- } else {
- $result = $sub->insert();
- }
-
- if (!$result) {
- common_log_db_error($sub, ($sub_exists) ? 'UPDATE' : 'INSERT', __FILE__);
- $this->clientError(_('Couldn\'t insert new subscription.'));
- return;
+ if (!$remote->update($orig_remote)) {
+ $this->serverError(_('Error updating remote profile'));
+ return;
}
- # Notify user, if necessary
-
- mail_subscribe_notify_profile($user, $profile);
-
- # Clear the data
+ /* Clear the session data. */
unset($_SESSION['oauth_authorization_request']);
- # If we show subscriptions in reverse chron order, this should
- # show up close to the top of the page
-
+ /* If we show subscriptions in reverse chronological order, the new one
+ should show up close to the top of the page. */
common_redirect(common_local_url('subscribers', array('nickname' =>
$user->nickname)),
303);
}
-
- function add_avatar($profile, $url)
- {
- $temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
- copy($url, $temp_filename);
- $imagefile = new ImageFile($profile->id, $temp_filename);
- $filename = Avatar::filename($profile->id,
- image_type_to_extension($imagefile->type),
- null,
- common_timestamp());
- rename($temp_filename, Avatar::path($filename));
- return $profile->setOriginal($filename);
- }
-
- function access_token($omb)
- {
-
- common_debug('starting request for access token', __FILE__);
-
- $con = omb_oauth_consumer();
- $tok = new OAuthToken($omb['token'], $omb['secret']);
-
- common_debug('using request token "'.$tok.'"', __FILE__);
-
- $url = $omb['access_token_url'];
-
- common_debug('using access token url "'.$url.'"', __FILE__);
-
- # XXX: Is this the right thing to do? Strip off GET params and make them
- # POST params? Seems wrong to me.
-
- $parsed = parse_url($url);
- $params = array();
- parse_str($parsed['query'], $params);
-
- $req = OAuthRequest::from_consumer_and_token($con, $tok, "POST", $url, $params);
-
- $req->set_parameter('omb_version', OMB_VERSION_01);
-
- # XXX: test to see if endpoint accepts this signature method
-
- $req->sign_request(omb_hmac_sha1(), $con, $tok);
-
- # We re-use this tool's fetcher, since it's pretty good
-
- common_debug('posting to access token url "'.$req->get_normalized_http_url().'"', __FILE__);
- common_debug('posting request data "'.$req->to_postdata().'"', __FILE__);
-
- $fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
- $result = $fetcher->post($req->get_normalized_http_url(),
- $req->to_postdata(),
- array('User-Agent: Laconica/' . LACONICA_VERSION));
-
- common_debug('got result: "'.print_r($result,true).'"', __FILE__);
-
- if ($result->status != 200) {
- return null;
- }
-
- parse_str($result->body, $return);
-
- return array($return['oauth_token'], $return['oauth_token_secret']);
- }
}
diff --git a/actions/grouplogo.php b/actions/grouplogo.php
index 8f6158dac..87c68e2a2 100644
--- a/actions/grouplogo.php
+++ b/actions/grouplogo.php
@@ -428,13 +428,7 @@ class GrouplogoAction extends GroupDesignAction
function showStylesheets()
{
parent::showStylesheets();
- $jcropStyle =
- common_path('theme/base/css/jquery.Jcrop.css?version='.LACONICA_VERSION);
-
- $this->element('link', array('rel' => 'stylesheet',
- 'type' => 'text/css',
- 'href' => $jcropStyle,
- 'media' => 'screen, projection, tv'));
+ $this->cssLink('css/jquery.Jcrop.css','base','screen, projection, tv');
}
/**
@@ -448,13 +442,8 @@ class GrouplogoAction extends GroupDesignAction
parent::showScripts();
if ($this->mode == 'crop') {
- $jcropPack = common_path('js/jcrop/jquery.Jcrop.pack.js');
- $jcropGo = common_path('js/jcrop/jquery.Jcrop.go.js');
-
- $this->element('script', array('type' => 'text/javascript',
- 'src' => $jcropPack));
- $this->element('script', array('type' => 'text/javascript',
- 'src' => $jcropGo));
+ $this->script('js/jcrop/jquery.Jcrop.min.js');
+ $this->script('js/jcrop/jquery.Jcrop.go.js');
}
}
diff --git a/actions/grouprss.php b/actions/grouprss.php
index 2bdcaafb2..e1e2d2018 100644
--- a/actions/grouprss.php
+++ b/actions/grouprss.php
@@ -132,9 +132,10 @@ class groupRssAction extends Rss10Action
$c = array('url' => common_local_url('grouprss',
array('nickname' =>
$group->nickname)),
- 'title' => $group->nickname,
+ 'title' => sprintf(_('%s timeline'), $group->nickname),
'link' => common_local_url('showgroup', array('nickname' => $group->nickname)),
- 'description' => sprintf(_('Microblog by %s group'), $group->nickname));
+ 'description' => sprintf(_('Updates from members of %1$s on %2$s!'),
+ $group->nickname, common_config('site', 'name')));
return $c;
}
diff --git a/actions/groupsearch.php b/actions/groupsearch.php
index c50466ce6..7437166e6 100644
--- a/actions/groupsearch.php
+++ b/actions/groupsearch.php
@@ -82,7 +82,8 @@ class GroupsearchAction extends SearchAction
$message = _('If you can\'t find the group you\'re looking for, you can [create it](%%action.newgroup%%) yourself.');
}
else {
- $message = _('Why not [register an account](%%action.register%%) and [create the group](%%action.newgroup%%) yourself!');
+ $message = sprintf(_('Why not [register an account](%%%%action.%s%%%%) and [create the group](%%%%action.newgroup%%%%) yourself!'),
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin');
}
$this->elementStart('div', 'guide');
$this->raw(common_markup_to_html($message));
diff --git a/actions/imsettings.php b/actions/imsettings.php
index e0f5ede3a..70a6f37d4 100644
--- a/actions/imsettings.php
+++ b/actions/imsettings.php
@@ -84,6 +84,12 @@ class ImsettingsAction extends ConnectSettingsAction
function showContent()
{
+ if (!common_config('xmpp', 'enabled')) {
+ $this->element('div', array('class' => 'error'),
+ _('IM is not available.'));
+ return;
+ }
+
$user = common_current_user();
$this->elementStart('form', array('method' => 'post',
'id' => 'form_settings_im',
diff --git a/actions/invite.php b/actions/invite.php
index 26c951ed2..bdc0d34cb 100644
--- a/actions/invite.php
+++ b/actions/invite.php
@@ -235,7 +235,7 @@ class InviteAction extends CurrentUserDesignAction
common_root_url(),
$personal,
common_local_url('showstream', array('nickname' => $user->nickname)),
- common_local_url('register', array('code' => $invite->code)));
+ common_local_url((!common_config('site', 'openidonly')) ? 'register' : 'openidlogin', array('code' => $invite->code)));
mail_send($recipients, $headers, $body);
}
diff --git a/actions/login.php b/actions/login.php
index f5a658bf5..e09fdc76b 100644
--- a/actions/login.php
+++ b/actions/login.php
@@ -247,7 +247,7 @@ class LoginAction extends Action
return _('For security reasons, please re-enter your ' .
'user name and password ' .
'before changing your settings.');
- } else {
+ } else if (common_config('openid', 'enabled')) {
return _('Login with your username and password. ' .
'Don\'t have a username yet? ' .
'[Register](%%action.register%%) a new account.');
diff --git a/actions/newgroup.php b/actions/newgroup.php
index 0289e77c2..71647d834 100644
--- a/actions/newgroup.php
+++ b/actions/newgroup.php
@@ -146,8 +146,8 @@ class NewgroupAction extends Action
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
$this->showForm(_('Full name is too long (max 255 chars).'));
return;
- } else if (!is_null($description) && mb_strlen($description) > 140) {
- $this->showForm(_('description is too long (max 140 chars).'));
+ } else if (User_group::descriptionTooLong($description)) {
+ $this->showForm(sprintf(_('description is too long (max %d chars).'), User_group::maxDescription()));
return;
} else if (!is_null($location) && mb_strlen($location) > 255) {
$this->showForm(_('Location is too long (max 255 chars).'));
diff --git a/actions/newmessage.php b/actions/newmessage.php
index 52d4899ba..cd26e1640 100644
--- a/actions/newmessage.php
+++ b/actions/newmessage.php
@@ -144,9 +144,10 @@ class NewmessageAction extends Action
} else {
$content_shortened = common_shorten_links($this->content);
- if (mb_strlen($content_shortened) > 140) {
- $this->showForm(_('That\'s too long. ' .
- 'Max message size is 140 chars.'));
+ if (Message::contentTooLong($content_shortened)) {
+ $this->showForm(sprintf(_('That\'s too long. ' .
+ 'Max message size is %d chars.'),
+ Message::maxContent()));
return;
}
}
diff --git a/actions/newnotice.php b/actions/newnotice.php
index e254eac49..049d7c322 100644
--- a/actions/newnotice.php
+++ b/actions/newnotice.php
@@ -91,8 +91,8 @@ class NewnoticeAction extends Action
// is losts when size is exceeded
if (empty($_POST) && $_SERVER['CONTENT_LENGTH']) {
$this->clientError(sprintf(_('The server was unable to handle ' .
- 'that much POST data (%s bytes) due to its current configuration.'),
- $_SERVER['CONTENT_LENGTH']));
+ 'that much POST data (%s bytes) due to its current configuration.'),
+ $_SERVER['CONTENT_LENGTH']));
}
parent::handle($args);
@@ -130,7 +130,7 @@ class NewnoticeAction extends Action
$hint = '';
}
$this->clientError(sprintf(
- _('%s is not a supported filetype on this server.'), $filetype) . $hint);
+ _('%s is not a supported filetype on this server.'), $filetype) . $hint);
}
function isRespectsQuota($user) {
@@ -162,9 +162,10 @@ class NewnoticeAction extends Action
$this->clientError(_('No content!'));
} else {
$content_shortened = common_shorten_links($content);
- if (mb_strlen($content_shortened) > 140) {
- $this->clientError(_('That\'s too long. '.
- 'Max notice size is 140 chars.'));
+ if (Notice::contentTooLong($content_shortened)) {
+ $this->clientError(sprintf(_('That\'s too long. '.
+ 'Max notice size is %d chars.'),
+ Notice::maxContent()));
}
}
@@ -190,37 +191,37 @@ class NewnoticeAction extends Action
if (isset($_FILES['attach']['error'])) {
switch ($_FILES['attach']['error']) {
- case UPLOAD_ERR_NO_FILE:
- // no file uploaded, nothing to do
- break;
+ case UPLOAD_ERR_NO_FILE:
+ // no file uploaded, nothing to do
+ break;
- case UPLOAD_ERR_OK:
- $mimetype = $this->getUploadedFileType();
- if (!$this->isRespectsQuota($user)) {
- die('clientError() should trigger an exception before reaching here.');
- }
- break;
+ case UPLOAD_ERR_OK:
+ $mimetype = $this->getUploadedFileType();
+ if (!$this->isRespectsQuota($user)) {
+ die('clientError() should trigger an exception before reaching here.');
+ }
+ break;
- case UPLOAD_ERR_INI_SIZE:
- $this->clientError(_('The uploaded file exceeds the upload_max_filesize directive in php.ini.'));
+ case UPLOAD_ERR_INI_SIZE:
+ $this->clientError(_('The uploaded file exceeds the upload_max_filesize directive in php.ini.'));
- case UPLOAD_ERR_FORM_SIZE:
- $this->clientError(_('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'));
+ case UPLOAD_ERR_FORM_SIZE:
+ $this->clientError(_('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'));
- case UPLOAD_ERR_PARTIAL:
- $this->clientError(_('The uploaded file was only partially uploaded.'));
+ case UPLOAD_ERR_PARTIAL:
+ $this->clientError(_('The uploaded file was only partially uploaded.'));
- case UPLOAD_ERR_NO_TMP_DIR:
- $this->clientError(_('Missing a temporary folder.'));
+ case UPLOAD_ERR_NO_TMP_DIR:
+ $this->clientError(_('Missing a temporary folder.'));
- case UPLOAD_ERR_CANT_WRITE:
- $this->clientError(_('Failed to write file to disk.'));
+ case UPLOAD_ERR_CANT_WRITE:
+ $this->clientError(_('Failed to write file to disk.'));
- case UPLOAD_ERR_EXTENSION:
- $this->clientError(_('File upload stopped by extension.'));
+ case UPLOAD_ERR_EXTENSION:
+ $this->clientError(_('File upload stopped by extension.'));
- default:
- die('Should never reach here.');
+ default:
+ die('Should never reach here.');
}
}
@@ -233,7 +234,7 @@ class NewnoticeAction extends Action
$fileRecord = $this->storeFile($filename, $mimetype);
$fileurl = common_local_url('attachment',
- array('attachment' => $fileRecord->id));
+ array('attachment' => $fileRecord->id));
// not sure this is necessary -- Zach
$this->maybeAddRedir($fileRecord->id, $fileurl);
@@ -241,9 +242,10 @@ class NewnoticeAction extends Action
$short_fileurl = common_shorten_url($fileurl);
$content_shortened .= ' ' . $short_fileurl;
- if (mb_strlen($content_shortened) > 140) {
+ if (Notice::contentTooLong($content_shortened)) {
$this->deleteFile($filename);
- $this->clientError(_('Max notice size is 140 chars, including attachment URL.'));
+ $this->clientError(sprintf(_('Max notice size is %d chars, including attachment URL.'),
+ Notice::maxContent()));
}
// Also, not sure this is necessary -- Zach
@@ -367,7 +369,7 @@ class NewnoticeAction extends Action
File_to_post::processNew($filerec->id, $notice->id);
$this->maybeAddRedir($filerec->id,
- common_local_url('file', array('notice' => $notice->id)));
+ common_local_url('file', array('notice' => $notice->id)));
}
/**
diff --git a/actions/noticesearch.php b/actions/noticesearch.php
index 49b473d9e..90b3309cf 100644
--- a/actions/noticesearch.php
+++ b/actions/noticesearch.php
@@ -121,7 +121,9 @@ class NoticesearchAction extends SearchAction
$message = sprintf(_('Be the first to [post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!'), urlencode($q));
}
else {
- $message = sprintf(_('Why not [register an account](%%%%action.register%%%%) and be the first to [post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!'), urlencode($q));
+ $message = sprintf(_('Why not [register an account](%%%%action.%s%%%%) and be the first to [post on this topic](%%%%action.newnotice%%%%?status_textarea=%s)!'),
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin',
+ urlencode($q));
}
$this->elementStart('div', 'guide');
diff --git a/actions/noticesearchrss.php b/actions/noticesearchrss.php
index 2a4b2060d..045531c5a 100644
--- a/actions/noticesearchrss.php
+++ b/actions/noticesearchrss.php
@@ -86,9 +86,10 @@ class NoticesearchrssAction extends Rss10Action
{
$q = $this->trimmed('q');
$c = array('url' => common_local_url('noticesearchrss', array('q' => $q)),
- 'title' => common_config('site', 'name') . sprintf(_(' Search Stream for "%s"'), $q),
+ 'title' => sprintf(_('Updates with "%s"'), $q),
'link' => common_local_url('noticesearch', array('q' => $q)),
- 'description' => sprintf(_('All updates matching search term "%s"'), $q));
+ 'description' => sprintf(_('Updates matching search term "%1$s" on %2$s!'),
+ $q, common_config('site', 'name')));
return $c;
}
diff --git a/actions/twitapioembed.php b/actions/oembed.php
index 3019e5878..3e46a7262 100644
--- a/actions/twitapioembed.php
+++ b/actions/oembed.php
@@ -31,8 +31,6 @@ if (!defined('LACONICA')) {
exit(1);
}
-require_once INSTALLDIR.'/lib/twitterapi.php';
-
/**
* Oembed provider implementation
*
@@ -46,17 +44,13 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
* @link http://laconi.ca/
*/
-class TwitapioembedAction extends TwitterapiAction
+class OembedAction extends Action
{
- function oembed($args, $apidata)
+ function handle($args)
{
- parent::handle($args);
-
common_debug("in oembed api action");
- $this->auth_user = $apidata['user'];
-
$url = $args['url'];
if( substr(strtolower($url),0,strlen(common_root_url())) == strtolower(common_root_url()) ){
$path = substr($url,strlen(common_root_url()));
@@ -131,8 +125,7 @@ class TwitapioembedAction extends TwitterapiAction
default:
$this->serverError(_("$path not supported for oembed requests"), 501);
}
-
- switch($apidata['content-type']){
+ switch($args['format']){
case 'xml':
$this->init_document('xml');
$this->elementStart('oembed');
@@ -151,12 +144,11 @@ class TwitapioembedAction extends TwitterapiAction
if($oembed['thumbnail_url']) $this->element('thumbnail_url',null,$oembed['thumbnail_url']);
if($oembed['thumbnail_width']) $this->element('thumbnail_width',null,$oembed['thumbnail_width']);
if($oembed['thumbnail_height']) $this->element('thumbnail_height',null,$oembed['thumbnail_height']);
-
$this->elementEnd('oembed');
$this->end_document('xml');
break;
- case 'json':
+ case 'json': case '':
$this->init_document('json');
print(json_encode($oembed));
$this->end_document('json');
@@ -164,10 +156,51 @@ class TwitapioembedAction extends TwitterapiAction
default:
$this->serverError(_('content type ' . $apidata['content-type'] . ' not supported'), 501);
}
-
}else{
$this->serverError(_('Only ' . common_root_url() . ' urls over plain http please'), 404);
}
}
-}
+ function init_document($type)
+ {
+ switch ($type) {
+ case 'xml':
+ header('Content-Type: application/xml; charset=utf-8');
+ $this->startXML();
+ break;
+ case 'json':
+ header('Content-Type: application/json; charset=utf-8');
+
+ // Check for JSONP callback
+ $callback = $this->arg('callback');
+ if ($callback) {
+ print $callback . '(';
+ }
+ break;
+ default:
+ $this->serverError(_('Not a supported data format.'), 501);
+ break;
+ }
+ }
+
+ function end_document($type='xml')
+ {
+ switch ($type) {
+ case 'xml':
+ $this->endXML();
+ break;
+ case 'json':
+ // Check for JSONP callback
+ $callback = $this->arg('callback');
+ if ($callback) {
+ print ')';
+ }
+ break;
+ default:
+ $this->serverError(_('Not a supported data format.'), 501);
+ break;
+ }
+ return;
+ }
+
+}
diff --git a/actions/opensearch.php b/actions/opensearch.php
index 4fe95c93b..6044568f1 100644
--- a/actions/opensearch.php
+++ b/actions/opensearch.php
@@ -66,7 +66,7 @@ class OpensearchAction extends Action
$type = 'noticesearch';
$short_name = _('Notice Search');
}
- header('Content-Type: text/html');
+ header('Content-Type: application/opensearchdescription+xml');
$this->startXML();
$this->elementStart('OpenSearchDescription', array('xmlns' => 'http://a9.com/-/spec/opensearch/1.1/'));
$short_name = common_config('site', 'name').' '.$short_name;
diff --git a/actions/postnotice.php b/actions/postnotice.php
index eb2d63b61..14152a83d 100644
--- a/actions/postnotice.php
+++ b/actions/postnotice.php
@@ -1,5 +1,16 @@
<?php
-/*
+/**
+ * Handle postnotice action
+ *
+ * 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.
*
@@ -17,75 +28,71 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
-require_once(INSTALLDIR.'/lib/omb.php');
+require_once INSTALLDIR.'/lib/omb.php';
+require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
+/**
+ * Handler for postnotice action
+ *
+ * @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 PostnoticeAction extends Action
{
+ /**
+ * For initializing members of the class.
+ *
+ * @param array $argarray misc. arguments
+ *
+ * @return boolean true
+ */
+ function prepare($argarray)
+ {
+ parent::prepare($argarray);
+ try {
+ $this->checkNotice();
+ } catch (Exception $e) {
+ $this->clientError($e->getMessage());
+ return false;
+ }
+ return true;
+ }
+
function handle($args)
{
parent::handle($args);
try {
- common_remove_magic_from_request();
- $req = OAuthRequest::from_request('POST', common_local_url('postnotice'));
- # Note: server-to-server function!
- $server = omb_oauth_server();
- list($consumer, $token) = $server->verify_request($req);
- if ($this->save_notice($req, $consumer, $token)) {
- print "omb_version=".OMB_VERSION_01;
- }
- } catch (OAuthException $e) {
+ $srv = new OMB_Service_Provider(null, omb_oauth_datastore(),
+ omb_oauth_server());
+ $srv->handlePostNotice();
+ } catch (Exception $e) {
$this->serverError($e->getMessage());
return;
}
}
- function save_notice(&$req, &$consumer, &$token)
+ function checkNotice()
{
- $version = $req->get_parameter('omb_version');
- if ($version != OMB_VERSION_01) {
- $this->clientError(_('Unsupported OMB version'), 400);
- return false;
- }
- # First, check to see
- $listenee = $req->get_parameter('omb_listenee');
- $remote_profile = Remote_profile::staticGet('uri', $listenee);
- if (!$remote_profile) {
- $this->clientError(_('Profile unknown'), 403);
- return false;
- }
- $sub = Subscription::staticGet('token', $token->key);
- if (!$sub) {
- $this->clientError(_('No such subscription'), 403);
- return false;
- }
- $content = $req->get_parameter('omb_notice_content');
- $content_shortened = common_shorten_links($content);
- if (mb_strlen($content_shortened) > 140) {
+ $content = common_shorten_links($_POST['omb_notice_content']);
+ if (Notice::contentTooLong($content)) {
$this->clientError(_('Invalid notice content'), 400);
return false;
}
- $notice_uri = $req->get_parameter('omb_notice');
- if (!Validate::uri($notice_uri) &&
- !common_valid_tag($notice_uri)) {
- $this->clientError(_('Invalid notice uri'), 400);
- return false;
- }
- $notice_url = $req->get_parameter('omb_notice_url');
- if ($notice_url && !common_valid_http_url($notice_url)) {
- $this->clientError(_('Invalid notice url'), 400);
- return false;
- }
- $notice = Notice::staticGet('uri', $notice_uri);
- if (!$notice) {
- $notice = Notice::saveNew($remote_profile->id, $content, 'omb', false, null, $notice_uri);
- if (is_string($notice)) {
- common_server_serror($notice, 500);
- return false;
- }
- common_broadcast_notice($notice, true);
+ $license = $_POST['omb_notice_license'];
+ $site_license = common_config('license', 'url');
+ if ($license && !common_compatible_license($license, $site_license)) {
+ throw new Exception(sprintf(_('Notice license ‘%s’ is not ' .
+ 'compatible with site license ‘%s’.'),
+ $license, $site_license));
}
- return true;
}
}
+?>
diff --git a/actions/profilesettings.php b/actions/profilesettings.php
index fb847680b..f429a2e51 100644
--- a/actions/profilesettings.php
+++ b/actions/profilesettings.php
@@ -109,9 +109,16 @@ class ProfilesettingsAction extends AccountSettingsAction
_('URL of your homepage, blog, or profile on another site'));
$this->elementEnd('li');
$this->elementStart('li');
+ $maxBio = Profile::maxBio();
+ if ($maxBio > 0) {
+ $bioInstr = sprintf(_('Describe yourself and your interests in %d chars'),
+ $maxBio);
+ } else {
+ $bioInstr = _('Describe yourself and your interests');
+ }
$this->textarea('bio', _('Bio'),
($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
- _('Describe yourself and your interests in 140 chars'));
+ $bioInstr);
$this->elementEnd('li');
$this->elementStart('li');
$this->input('location', _('Location'),
@@ -189,7 +196,7 @@ class ProfilesettingsAction extends AccountSettingsAction
// Some validation
if (!Validate::string($nickname, array('min_length' => 1,
'max_length' => 64,
- 'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
+ 'format' => NICKNAME_FMT))) {
$this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.'));
return;
} else if (!User::allowed_nickname($nickname)) {
@@ -202,8 +209,9 @@ class ProfilesettingsAction extends AccountSettingsAction
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
$this->showForm(_('Full name is too long (max 255 chars).'));
return;
- } else if (!is_null($bio) && mb_strlen($bio) > 140) {
- $this->showForm(_('Bio is too long (max 140 chars).'));
+ } else if (Profile::bioTooLong($bio)) {
+ $this->showForm(sprintf(_('Bio is too long (max %d chars).'),
+ Profile::maxBio()));
return;
} else if (!is_null($location) && mb_strlen($location) > 255) {
$this->showForm(_('Location is too long (max 255 chars).'));
diff --git a/actions/public.php b/actions/public.php
index 322a52963..b68b2ff79 100644
--- a/actions/public.php
+++ b/actions/public.php
@@ -59,6 +59,7 @@ class PublicAction extends Action
*/
var $page = null;
+ var $notice;
function isReadOnly($args)
{
@@ -84,6 +85,18 @@ class PublicAction extends Action
common_set_returnto($this->selfUrl());
+ $this->notice = Notice::publicStream(($this->page-1)*NOTICES_PER_PAGE,
+ NOTICES_PER_PAGE + 1);
+
+ if (!$this->notice) {
+ $this->serverError(_('Could not retrieve public stream.'));
+ return;
+ }
+
+ if($this->page > 1 && $this->notice->N == 0){
+ $this->serverError(_('No such page'),$code=404);
+ }
+
return true;
}
@@ -165,7 +178,8 @@ class PublicAction extends Action
}
else {
if (! (common_config('site','closed') || common_config('site','inviteonly'))) {
- $message .= _('Why not [register an account](%%action.register%%) and be the first to post!');
+ $message .= sprintf(_('Why not [register an account](%%%%action.%s%%%%) and be the first to post!'),
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin');
}
}
@@ -185,15 +199,7 @@ class PublicAction extends Action
function showContent()
{
- $notice = Notice::publicStream(($this->page-1)*NOTICES_PER_PAGE,
- NOTICES_PER_PAGE + 1);
-
- if (!$notice) {
- $this->serverError(_('Could not retrieve public stream.'));
- return;
- }
-
- $nl = new NoticeList($notice, $this);
+ $nl = new NoticeList($this->notice, $this);
$cnt = $nl->show();
@@ -220,9 +226,11 @@ class PublicAction extends Action
function showAnonymousMessage()
{
if (! (common_config('site','closed') || common_config('site','inviteonly'))) {
- $m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
- 'based on the Free Software [Laconica](http://laconi.ca/) tool. ' .
- '[Join now](%%action.register%%) to share notices about yourself with friends, family, and colleagues! ([Read more](%%doc.help%%))');
+ $m = sprintf(_('This is %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
+ 'based on the Free Software [Laconica](http://laconi.ca/) tool. ' .
+ '[Join now](%%%%action.%s%%%%) to share notices about yourself with friends, family, and colleagues! ' .
+ '([Read more](%%%%doc.help%%%%))'),
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin');
} else {
$m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [Laconica](http://laconi.ca/) tool.');
diff --git a/actions/publicrss.php b/actions/publicrss.php
index 7e8df9625..5c08de641 100644
--- a/actions/publicrss.php
+++ b/actions/publicrss.php
@@ -86,9 +86,9 @@ class PublicrssAction extends Rss10Action
{
$c = array(
'url' => common_local_url('publicrss')
- , 'title' => sprintf(_('%s Public Stream'), common_config('site', 'name'))
+ , 'title' => sprintf(_('%s public timeline'), common_config('site', 'name'))
, 'link' => common_local_url('public')
- , 'description' => sprintf(_('All updates for %s'), common_config('site', 'name')));
+ , 'description' => sprintf(_('%s updates from everyone!'), common_config('site', 'name')));
return $c;
}
diff --git a/actions/publictagcloud.php b/actions/publictagcloud.php
index e9f33d58b..a2772869d 100644
--- a/actions/publictagcloud.php
+++ b/actions/publictagcloud.php
@@ -72,7 +72,8 @@ class PublictagcloudAction extends Action
$message .= _('Be the first to post one!');
}
else {
- $message .= _('Why not [register an account](%%action.register%%) and be the first to post one!');
+ $message .= sprintf(_('Why not [register an account](%%%%action.%s%%%%) and be the first to post one!'),
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin');
}
$this->elementStart('div', 'guide');
diff --git a/actions/register.php b/actions/register.php
index dd3edc4ed..aa295c097 100644
--- a/actions/register.php
+++ b/actions/register.php
@@ -207,8 +207,9 @@ class RegisterAction extends Action
} else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
$this->showForm(_('Full name is too long (max 255 chars).'));
return;
- } else if (!is_null($bio) && mb_strlen($bio) > 140) {
- $this->showForm(_('Bio is too long (max 140 chars).'));
+ } else if (Profile::bioTooLong($bio)) {
+ $this->showForm(sprintf(_('Bio is too long (max %d chars).'),
+ Profile::maxBio()));
return;
} else if (!is_null($location) && mb_strlen($location) > 255) {
$this->showForm(_('Location is too long (max 255 chars).'));
@@ -442,10 +443,16 @@ class RegisterAction extends Action
'or profile on another site'));
$this->elementEnd('li');
$this->elementStart('li');
+ $maxBio = Profile::maxBio();
+ if ($maxBio > 0) {
+ $bioInstr = sprintf(_('Describe yourself and your interests in %d chars'),
+ $maxBio);
+ } else {
+ $bioInstr = _('Describe yourself and your interests');
+ }
$this->textarea('bio', _('Bio'),
$this->trimmed('bio'),
- _('Describe yourself and your '.
- 'interests in 140 chars'));
+ $bioInstr);
$this->elementEnd('li');
$this->elementStart('li');
$this->input('location', _('Location'),
diff --git a/actions/remotesubscribe.php b/actions/remotesubscribe.php
index e658f8d37..90499bbe2 100644
--- a/actions/remotesubscribe.php
+++ b/actions/remotesubscribe.php
@@ -1,5 +1,16 @@
<?php
-/*
+/**
+ * Handler for remote subscription
+ *
+ * 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.
*
@@ -15,11 +26,26 @@
*
* 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); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/lib/omb.php';
+require_once INSTALLDIR.'/extlib/libomb/service_consumer.php';
+require_once INSTALLDIR.'/extlib/libomb/profile.php';
-require_once(INSTALLDIR.'/lib/omb.php');
+/**
+ * Handler for remote subscription
+ *
+ * @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 RemotesubscribeAction extends Action
{
@@ -36,7 +62,7 @@ class RemotesubscribeAction extends Action
return false;
}
- $this->nickname = $this->trimmed('nickname');
+ $this->nickname = $this->trimmed('nickname');
$this->profile_url = $this->trimmed('profile_url');
return true;
@@ -47,7 +73,7 @@ class RemotesubscribeAction extends Action
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
- # CSRF protection
+ /* Use a session token for CSRF protection. */
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
$this->showForm(_('There was a problem with your session token. '.
@@ -71,11 +97,13 @@ class RemotesubscribeAction extends Action
if ($this->err) {
$this->element('div', 'error', $this->err);
} else {
- $inst = _('To subscribe, you can [login](%%action.login%%),' .
- ' or [register](%%action.register%%) a new ' .
- ' account. If you already have an account ' .
- ' on a [compatible microblogging site](%%doc.openmublog%%), ' .
- ' enter your profile URL below.');
+ $inst = sprintf(_('To subscribe, you can [login](%%%%action.%s%%%%),' .
+ ' or [register](%%%%action.%s%%%%) a new ' .
+ ' account. If you already have an account ' .
+ ' on a [compatible microblogging site](%%doc.openmublog%%), ' .
+ ' enter your profile URL below.'),
+ (!common_config('site','openidonly')) ? 'login' : 'openidlogin',
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin');
$output = common_markup_to_html($inst);
$this->elementStart('div', 'instructions');
$this->raw($output);
@@ -90,8 +118,8 @@ class RemotesubscribeAction extends Action
function showContent()
{
- # id = remotesubscribe conflicts with the
- # button on profile page
+ /* The id 'remotesubscribe' conflicts with the
+ button on profile page. */
$this->elementStart('form', array('id' => 'form_remote_subscribe',
'method' => 'post',
'class' => 'form_settings',
@@ -117,247 +145,50 @@ class RemotesubscribeAction extends Action
function remoteSubscription()
{
- $user = $this->getUser();
-
- if (!$user) {
+ if (!$this->nickname) {
$this->showForm(_('No such user.'));
return;
}
+ $user = User::staticGet('nickname', $this->nickname);
+
$this->profile_url = $this->trimmed('profile_url');
if (!$this->profile_url) {
- $this->showForm(_('No such user.'));
+ $this->showForm(_('No such user'));
return;
}
- if (!Validate::uri($this->profile_url, array('allowed_schemes' => array('http', 'https')))) {
+ if (!common_valid_http_url($this->profile_url)) {
$this->showForm(_('Invalid profile URL (bad format)'));
return;
}
- $fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
- $yadis = Auth_Yadis_Yadis::discover($this->profile_url, $fetcher);
-
- if (!$yadis || $yadis->failed) {
- $this->showForm(_('Not a valid profile URL (no YADIS document).'));
- return;
- }
-
- # XXX: a little liberal for sites that accidentally put whitespace before the xml declaration
-
- $xrds =& Auth_Yadis_XRDS::parseXRDS(trim($yadis->response_text));
-
- if (!$xrds) {
- $this->showForm(_('Not a valid profile URL (no XRDS defined).'));
- return;
- }
-
- $omb = $this->getOmb($xrds);
-
- if (!$omb) {
- $this->showForm(_('Not a valid profile URL (incorrect services).'));
- return;
- }
-
- if (omb_service_uri($omb[OAUTH_ENDPOINT_REQUEST]) ==
- common_local_url('requesttoken'))
- {
- $this->showForm(_('That\'s a local profile! Login to subscribe.'));
+ try {
+ $service = new OMB_Service_Consumer($this->profile_url,
+ common_root_url(),
+ omb_oauth_datastore());
+ } catch (OMB_InvalidYadisException $e) {
+ $this->showForm(_('Not a valid profile URL (no YADIS document or ' .
+ 'no or invalid XRDS defined).'));
return;
}
- if (User::staticGet('uri', omb_local_id($omb[OAUTH_ENDPOINT_REQUEST]))) {
- $this->showForm(_('That\'s a local profile! Login to subscribe.'));
+ if ($service->getServiceURI(OAUTH_ENDPOINT_REQUEST) ==
+ common_local_url('requesttoken') ||
+ User::staticGet('uri', $service->getRemoteUserURI())) {
+ $this->showForm(_('That’s a local profile! Login to subscribe.'));
return;
}
- list($token, $secret) = $this->requestToken($omb);
-
- if (!$token || !$secret) {
- $this->showForm(_('Couldn\'t get a request token.'));
+ try {
+ $service->requestToken();
+ } catch (OMB_RemoteServiceException $e) {
+ $this->showForm(_('Couldn’t get a request token.'));
return;
}
- $this->requestAuthorization($user, $omb, $token, $secret);
- }
-
- function getUser()
- {
- $user = null;
- if ($this->nickname) {
- $user = User::staticGet('nickname', $this->nickname);
- }
- return $user;
- }
-
- function getOmb($xrds)
- {
- static $omb_endpoints = array(OMB_ENDPOINT_UPDATEPROFILE, OMB_ENDPOINT_POSTNOTICE);
- static $oauth_endpoints = array(OAUTH_ENDPOINT_REQUEST, OAUTH_ENDPOINT_AUTHORIZE,
- OAUTH_ENDPOINT_ACCESS);
- $omb = array();
-
- # XXX: the following code could probably be refactored to eliminate dupes
-
- $oauth_services = omb_get_services($xrds, OAUTH_DISCOVERY);
-
- if (!$oauth_services) {
- return null;
- }
-
- $oauth_service = $oauth_services[0];
-
- $oauth_xrd = $this->getXRD($oauth_service, $xrds);
-
- if (!$oauth_xrd) {
- return null;
- }
-
- if (!$this->addServices($oauth_xrd, $oauth_endpoints, $omb)) {
- return null;
- }
-
- $omb_services = omb_get_services($xrds, OMB_NAMESPACE);
-
- if (!$omb_services) {
- return null;
- }
-
- $omb_service = $omb_services[0];
-
- $omb_xrd = $this->getXRD($omb_service, $xrds);
-
- if (!$omb_xrd) {
- return null;
- }
-
- if (!$this->addServices($omb_xrd, $omb_endpoints, $omb)) {
- return null;
- }
-
- # XXX: check that we got all the services we needed
-
- foreach (array_merge($omb_endpoints, $oauth_endpoints) as $type) {
- if (!array_key_exists($type, $omb) || !$omb[$type]) {
- return null;
- }
- }
-
- if (!omb_local_id($omb[OAUTH_ENDPOINT_REQUEST])) {
- return null;
- }
-
- return $omb;
- }
-
- function getXRD($main_service, $main_xrds)
- {
- $uri = omb_service_uri($main_service);
- if (strpos($uri, "#") !== 0) {
- # FIXME: more rigorous handling of external service definitions
- return null;
- }
- $id = substr($uri, 1);
- $nodes = $main_xrds->allXrdNodes;
- $parser = $main_xrds->parser;
- foreach ($nodes as $node) {
- $attrs = $parser->attributes($node);
- if (array_key_exists('xml:id', $attrs) &&
- $attrs['xml:id'] == $id) {
- # XXX: trick the constructor into thinking this is the only node
- $bogus_nodes = array($node);
- return new Auth_Yadis_XRDS($parser, $bogus_nodes);
- }
- }
- return null;
- }
-
- function addServices($xrd, $types, &$omb)
- {
- foreach ($types as $type) {
- $matches = omb_get_services($xrd, $type);
- if ($matches) {
- $omb[$type] = $matches[0];
- } else {
- # no match for type
- return false;
- }
- }
- return true;
- }
-
- function requestToken($omb)
- {
- $con = omb_oauth_consumer();
-
- $url = omb_service_uri($omb[OAUTH_ENDPOINT_REQUEST]);
-
- # XXX: Is this the right thing to do? Strip off GET params and make them
- # POST params? Seems wrong to me.
-
- $parsed = parse_url($url);
- $params = array();
- parse_str($parsed['query'], $params);
-
- $req = OAuthRequest::from_consumer_and_token($con, null, "POST", $url, $params);
-
- $listener = omb_local_id($omb[OAUTH_ENDPOINT_REQUEST]);
-
- if (!$listener) {
- return null;
- }
-
- $req->set_parameter('omb_listener', $listener);
- $req->set_parameter('omb_version', OMB_VERSION_01);
-
- # XXX: test to see if endpoint accepts this signature method
-
- $req->sign_request(omb_hmac_sha1(), $con, null);
-
- # We re-use this tool's fetcher, since it's pretty good
-
- $fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
-
- $result = $fetcher->post($req->get_normalized_http_url(),
- $req->to_postdata(),
- array('User-Agent: Laconica/' . LACONICA_VERSION));
- if ($result->status != 200) {
- return null;
- }
-
- parse_str($result->body, $return);
-
- return array($return['oauth_token'], $return['oauth_token_secret']);
- }
-
- function requestAuthorization($user, $omb, $token, $secret)
- {
- $con = omb_oauth_consumer();
- $tok = new OAuthToken($token, $secret);
-
- $url = omb_service_uri($omb[OAUTH_ENDPOINT_AUTHORIZE]);
-
- # XXX: Is this the right thing to do? Strip off GET params and make them
- # POST params? Seems wrong to me.
-
- $parsed = parse_url($url);
- $params = array();
- parse_str($parsed['query'], $params);
-
- $req = OAuthRequest::from_consumer_and_token($con, $tok, 'GET', $url, $params);
-
- # We send over a ton of information. This lets the other
- # server store info about our user, and it lets the current
- # user decide if they really want to authorize the subscription.
-
- $req->set_parameter('omb_version', OMB_VERSION_01);
- $req->set_parameter('omb_listener', omb_local_id($omb[OAUTH_ENDPOINT_REQUEST]));
- $req->set_parameter('omb_listenee', $user->uri);
- $req->set_parameter('omb_listenee_profile', common_profile_url($user->nickname));
- $req->set_parameter('omb_listenee_nickname', $user->nickname);
- $req->set_parameter('omb_listenee_license', common_config('license', 'url'));
-
+ /* Create an OMB_Profile from $user. */
$profile = $user->getProfile();
if (!$profile) {
common_log_db_error($user, 'SELECT', __FILE__);
@@ -365,49 +196,16 @@ class RemotesubscribeAction extends Action
return;
}
- if (!is_null($profile->fullname)) {
- $req->set_parameter('omb_listenee_fullname', $profile->fullname);
- }
- if (!is_null($profile->homepage)) {
- $req->set_parameter('omb_listenee_homepage', $profile->homepage);
- }
- if (!is_null($profile->bio)) {
- $req->set_parameter('omb_listenee_bio', $profile->bio);
- }
- if (!is_null($profile->location)) {
- $req->set_parameter('omb_listenee_location', $profile->location);
- }
- $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
- if ($avatar) {
- $req->set_parameter('omb_listenee_avatar', $avatar->url);
- }
-
- # XXX: add a nonce to prevent replay attacks
-
- $req->set_parameter('oauth_callback', common_local_url('finishremotesubscribe'));
-
- # XXX: test to see if endpoint accepts this signature method
-
- $req->sign_request(omb_hmac_sha1(), $con, $tok);
-
- # store all our info here
-
- $omb['listenee'] = $user->nickname;
- $omb['listener'] = omb_local_id($omb[OAUTH_ENDPOINT_REQUEST]);
- $omb['token'] = $token;
- $omb['secret'] = $secret;
- # call doesn't work after bounce back so we cache; maybe serialization issue...?
- $omb['access_token_url'] = omb_service_uri($omb[OAUTH_ENDPOINT_ACCESS]);
- $omb['post_notice_url'] = omb_service_uri($omb[OMB_ENDPOINT_POSTNOTICE]);
- $omb['update_profile_url'] = omb_service_uri($omb[OMB_ENDPOINT_UPDATEPROFILE]);
+ $target_url = $service->requestAuthorization(
+ profile_to_omb_profile($user->uri, $profile),
+ common_local_url('finishremotesubscribe'));
common_ensure_session();
- $_SESSION['oauth_authorization_request'] = $omb;
-
- # Redirect to authorization service
+ $_SESSION['oauth_authorization_request'] = serialize($service);
- common_redirect($req->to_url(), 303);
- return;
+ /* Redirect to the remote service for authorization. */
+ common_redirect($target_url, 303);
}
}
+?>
diff --git a/actions/replies.php b/actions/replies.php
index d7ed440e9..fcfc3a272 100644
--- a/actions/replies.php
+++ b/actions/replies.php
@@ -48,6 +48,7 @@ require_once INSTALLDIR.'/lib/feedlist.php';
class RepliesAction extends OwnerDesignAction
{
var $page = null;
+ var $notice;
/**
* Prepare the object
@@ -84,6 +85,13 @@ class RepliesAction extends OwnerDesignAction
common_set_returnto($this->selfUrl());
+ $this->notice = $this->user->getReplies(($this->page-1) * NOTICES_PER_PAGE,
+ NOTICES_PER_PAGE + 1);
+
+ if($this->page > 1 && $this->notice->N == 0){
+ $this->serverError(_('No such page'),$code=404);
+ }
+
return true;
}
@@ -159,10 +167,7 @@ class RepliesAction extends OwnerDesignAction
function showContent()
{
- $notice = $this->user->getReplies(($this->page-1) * NOTICES_PER_PAGE,
- NOTICES_PER_PAGE + 1);
-
- $nl = new NoticeList($notice, $this);
+ $nl = new NoticeList($this->notice, $this);
$cnt = $nl->show();
if (0 === $cnt) {
@@ -187,7 +192,9 @@ class RepliesAction extends OwnerDesignAction
}
}
else {
- $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname);
+ $message .= sprintf(_('Why not [register an account](%%%%action.%s%%%%) and then nudge %s or post a notice to his or her attention.'),
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin',
+ $this->user->nickname);
}
$this->elementStart('div', 'guide');
diff --git a/actions/repliesrss.php b/actions/repliesrss.php
index a87e2870d..580bb91f7 100644
--- a/actions/repliesrss.php
+++ b/actions/repliesrss.php
@@ -68,7 +68,8 @@ class RepliesrssAction extends Rss10Action
'link' => common_local_url('replies',
array('nickname' =>
$user->nickname)),
- 'description' => sprintf(_('Feed for replies to %s'), $user->nickname));
+ 'description' => sprintf(_('Replies to %1$s on %2$s!'),
+ $user->nickname, common_config('site', 'name')));
return $c;
}
diff --git a/actions/requesttoken.php b/actions/requesttoken.php
index 8d1e3f004..8328962f2 100644
--- a/actions/requesttoken.php
+++ b/actions/requesttoken.php
@@ -34,6 +34,7 @@ if (!defined('LACONICA')) {
}
require_once INSTALLDIR.'/lib/omb.php';
+require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
/**
* Request token action class.
@@ -49,17 +50,17 @@ class RequesttokenAction extends Action
{
/**
* Is read only?
- *
+ *
* @return boolean false
*/
- function isReadOnly($args)
+ function isReadOnly()
{
return false;
}
-
+
/**
* Class handler.
- *
+ *
* @param array $args array of arguments
*
* @return void
@@ -68,14 +69,12 @@ class RequesttokenAction extends Action
{
parent::handle($args);
try {
- common_remove_magic_from_request();
- $req = OAuthRequest::from_request('POST', common_local_url('requesttoken'));
- $server = omb_oauth_server();
- $token = $server->fetch_request_token($req);
- print $token;
- } catch (OAuthException $e) {
+ $srv = new OMB_Service_Provider(null, omb_oauth_datastore(),
+ omb_oauth_server());
+ $srv->writeRequestToken();
+ } catch (Exception $e) {
$this->serverError($e->getMessage());
}
}
}
-
+?>
diff --git a/actions/showfavorites.php b/actions/showfavorites.php
index 8efe9d30a..91287cc96 100644
--- a/actions/showfavorites.php
+++ b/actions/showfavorites.php
@@ -114,6 +114,29 @@ class ShowfavoritesAction extends OwnerDesignAction
common_set_returnto($this->selfUrl());
+ $cur = common_current_user();
+
+ if (!empty($cur) && $cur->id == $this->user->id) {
+
+ // Show imported/gateway notices as well as local if
+ // the user is looking at his own favorites
+
+ $this->notice = $this->user->favoriteNotices(($this->page-1)*NOTICES_PER_PAGE,
+ NOTICES_PER_PAGE + 1, true);
+ } else {
+ $this->notice = $this->user->favoriteNotices(($this->page-1)*NOTICES_PER_PAGE,
+ NOTICES_PER_PAGE + 1, false);
+ }
+
+ if (empty($this->notice)) {
+ $this->serverError(_('Could not retrieve favorite notices.'));
+ return;
+ }
+
+ if($this->page > 1 && $this->notice->N == 0){
+ $this->serverError(_('No such page'),$code=404);
+ }
+
return true;
}
@@ -173,7 +196,9 @@ class ShowfavoritesAction extends OwnerDesignAction
}
}
else {
- $message = sprintf(_('%s hasn\'t added any notices to his favorites yet. Why not [register an account](%%%%action.register%%%%) and then post something interesting they would add to thier favorites :)'), $this->user->nickname);
+ $message = sprintf(_('%s hasn\'t added any notices to his favorites yet. Why not [register an account](%%%%action.%s%%%%) and then post something interesting they would add to their favorites :)'),
+ $this->user->nickname,
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin');
}
$this->elementStart('div', 'guide');
@@ -191,26 +216,7 @@ class ShowfavoritesAction extends OwnerDesignAction
function showContent()
{
- $cur = common_current_user();
-
- if (!empty($cur) && $cur->id == $this->user->id) {
-
- // Show imported/gateway notices as well as local if
- // the user is looking at his own favorites
-
- $notice = $this->user->favoriteNotices(($this->page-1)*NOTICES_PER_PAGE,
- NOTICES_PER_PAGE + 1, true);
- } else {
- $notice = $this->user->favoriteNotices(($this->page-1)*NOTICES_PER_PAGE,
- NOTICES_PER_PAGE + 1, false);
- }
-
- if (empty($notice)) {
- $this->serverError(_('Could not retrieve favorite notices.'));
- return;
- }
-
- $nl = new NoticeList($notice, $this);
+ $nl = new NoticeList($this->notice, $this);
$cnt = $nl->show();
if (0 == $cnt) {
diff --git a/actions/showgroup.php b/actions/showgroup.php
index 32ec674a9..b0cc1dbc7 100644
--- a/actions/showgroup.php
+++ b/actions/showgroup.php
@@ -130,8 +130,18 @@ class ShowgroupAction extends GroupDesignAction
$this->group = User_group::staticGet('nickname', $nickname);
if (!$this->group) {
- $this->clientError(_('No such group'), 404);
- return false;
+ $alias = Group_alias::staticGet('alias', $nickname);
+ if ($alias) {
+ $args = array('id' => $alias->group_id);
+ if ($this->page != 1) {
+ $args['page'] = $this->page;
+ }
+ common_redirect(common_local_url('groupbyid', $args), 301);
+ return false;
+ } else {
+ $this->clientError(_('No such group'), 404);
+ return false;
+ }
}
common_set_returnto($this->selfUrl());
@@ -440,8 +450,9 @@ class ShowgroupAction extends GroupDesignAction
$m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [Laconica](http://laconi.ca/) tool. Its members share ' .
'short messages about their life and interests. '.
- '[Join now](%%%%action.register%%%%) to become part of this group and many more! ([Read more](%%%%doc.help%%%%))'),
- $this->group->nickname);
+ '[Join now](%%%%action.%s%%%%) to become part of this group and many more! ([Read more](%%%%doc.help%%%%))'),
+ $this->group->nickname,
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin');
} else {
$m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [Laconica](http://laconi.ca/) tool. Its members share ' .
diff --git a/actions/shownotice.php b/actions/shownotice.php
index 3d7319489..82031d90d 100644
--- a/actions/shownotice.php
+++ b/actions/shownotice.php
@@ -103,8 +103,8 @@ class ShownoticeAction extends OwnerDesignAction
$this->user = User::staticGet('id', $this->profile->id);
- if (empty($this->user)) {
- $this->serverError(_('Not a local notice'), 500);
+ if (! $this->notice->is_local) {
+ common_redirect($this->notice->uri);
return false;
}
@@ -196,7 +196,7 @@ class ShownoticeAction extends OwnerDesignAction
{
parent::handle($args);
- if ($this->notice->is_local == 0) {
+ if ($this->notice->is_local == Notice::REMOTE_OMB) {
if (!empty($this->notice->url)) {
common_redirect($this->notice->url, 301);
} else if (!empty($this->notice->uri) && preg_match('/^https?:/', $this->notice->uri)) {
@@ -284,16 +284,16 @@ class ShownoticeAction extends OwnerDesignAction
$this->element('link',array('rel'=>'alternate',
'type'=>'application/json+oembed',
'href'=>common_local_url(
- 'api',
- array('apiaction'=>'oembed','method'=>'oembed.json'),
- array('url'=>$this->notice->uri)),
+ 'oembed',
+ array(),
+ array('format'=>'json','url'=>$this->notice->uri)),
'title'=>'oEmbed'),null);
$this->element('link',array('rel'=>'alternate',
'type'=>'text/xml+oembed',
'href'=>common_local_url(
- 'api',
- array('apiaction'=>'oembed','method'=>'oembed.xml'),
- array('url'=>$this->notice->uri)),
+ 'oembed',
+ array(),
+ array('format'=>'xml','url'=>$this->notice->uri)),
'title'=>'oEmbed'),null);
}
}
diff --git a/actions/showstream.php b/actions/showstream.php
index cd5d4bb70..3f603d64f 100644
--- a/actions/showstream.php
+++ b/actions/showstream.php
@@ -358,7 +358,9 @@ class ShowstreamAction extends ProfileAction
}
}
else {
- $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname);
+ $message .= sprintf(_('Why not [register an account](%%%%action.%s%%%%) and then nudge %s or post a notice to his or her attention.'),
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin',
+ $this->user->nickname);
}
$this->elementStart('div', 'guide');
@@ -387,8 +389,10 @@ class ShowstreamAction extends ProfileAction
if (!(common_config('site','closed') || common_config('site','inviteonly'))) {
$m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [Laconica](http://laconi.ca/) tool. ' .
- '[Join now](%%%%action.register%%%%) to follow **%s**\'s notices and many more! ([Read more](%%%%doc.help%%%%))'),
- $this->user->nickname, $this->user->nickname);
+ '[Join now](%%%%action.%s%%%%) to follow **%s**\'s notices and many more! ([Read more](%%%%doc.help%%%%))'),
+ $this->user->nickname,
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin',
+ $this->user->nickname);
} else {
$m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' .
'based on the Free Software [Laconica](http://laconi.ca/) tool. '),
diff --git a/actions/smssettings.php b/actions/smssettings.php
index 922bab9a4..33b54abf6 100644
--- a/actions/smssettings.php
+++ b/actions/smssettings.php
@@ -80,6 +80,12 @@ class SmssettingsAction extends ConnectSettingsAction
function showContent()
{
+ if (!common_config('sms', 'enabled')) {
+ $this->element('div', array('class' => 'error'),
+ _('SMS is not available.'));
+ return;
+ }
+
$user = common_current_user();
$this->elementStart('form', array('method' => 'post',
diff --git a/actions/subscribers.php b/actions/subscribers.php
index 66ac00fb1..404738012 100644
--- a/actions/subscribers.php
+++ b/actions/subscribers.php
@@ -111,7 +111,9 @@ class SubscribersAction extends GalleryAction
}
}
else {
- $message = sprintf(_('%s has no subscribers. Why not [register an account](%%%%action.register%%%%) and be the first?'), $this->user->nickname);
+ $message = sprintf(_('%s has no subscribers. Why not [register an account](%%%%action.%s%%%%) and be the first?'),
+ $this->user->nickname,
+ (!common_config('site','openidonly')) ? 'register' : 'openidlogin');
}
$this->elementStart('div', 'guide');
diff --git a/actions/subscriptions.php b/actions/subscriptions.php
index 42bdae10f..0724471ff 100644
--- a/actions/subscriptions.php
+++ b/actions/subscriptions.php
@@ -174,14 +174,26 @@ class SubscriptionsListItem extends SubscriptionListItem
return;
}
+ if (!common_config('xmpp', 'enabled') && !common_config('sms', 'enabled')) {
+ return;
+ }
+
$this->out->elementStart('form', array('id' => 'subedit-' . $this->profile->id,
'method' => 'post',
'class' => 'form_subscription_edit',
'action' => common_local_url('subedit')));
$this->out->hidden('token', common_session_token());
$this->out->hidden('profile', $this->profile->id);
- $this->out->checkbox('jabber', _('Jabber'), $sub->jabber);
- $this->out->checkbox('sms', _('SMS'), $sub->sms);
+ if (common_config('xmpp', 'enabled')) {
+ $this->out->checkbox('jabber', _('Jabber'), $sub->jabber);
+ } else {
+ $this->out->hidden('jabber', $sub->jabber);
+ }
+ if (common_config('sms', 'enabled')) {
+ $this->out->checkbox('sms', _('SMS'), $sub->sms);
+ } else {
+ $this->out->hidden('sms', $sub->sms);
+ }
$this->out->submit('save', _('Save'));
$this->out->elementEnd('form');
return;
diff --git a/actions/tag.php b/actions/tag.php
index 020399d9e..771eb2861 100644
--- a/actions/tag.php
+++ b/actions/tag.php
@@ -21,6 +21,9 @@ if (!defined('LACONICA')) { exit(1); }
class TagAction extends Action
{
+
+ var $notice;
+
function prepare($args)
{
parent::prepare($args);
@@ -42,6 +45,12 @@ class TagAction extends Action
common_set_returnto($this->selfUrl());
+ $this->notice = Notice_tag::getStream($this->tag, (($this->page-1)*NOTICES_PER_PAGE), NOTICES_PER_PAGE + 1);
+
+ if($this->page > 1 && $this->notice->N == 0){
+ $this->serverError(_('No such page'),$code=404);
+ }
+
return true;
}
@@ -94,9 +103,7 @@ class TagAction extends Action
function showContent()
{
- $notice = Notice_tag::getStream($this->tag, (($this->page-1)*NOTICES_PER_PAGE), NOTICES_PER_PAGE + 1);
-
- $nl = new NoticeList($notice, $this);
+ $nl = new NoticeList($this->notice, $this);
$cnt = $nl->show();
diff --git a/actions/tagrss.php b/actions/tagrss.php
index f69374fca..c3c03b9cd 100644
--- a/actions/tagrss.php
+++ b/actions/tagrss.php
@@ -61,7 +61,8 @@ class TagrssAction extends Rss10Action
$c = array('url' => common_local_url('tagrss', array('tag' => $tagname)),
'title' => $tagname,
'link' => common_local_url('tagrss', array('tag' => $tagname)),
- 'description' => sprintf(_('Microblog tagged with %s'), $tagname));
+ 'description' => sprintf(_('Updates tagged with %1$s on %2$s!'),
+ $tagname, common_config('site', 'name')));
return $c;
}
diff --git a/actions/twitapidirect_messages.php b/actions/twitapidirect_messages.php
index bd27e9d20..aac7d63b1 100644
--- a/actions/twitapidirect_messages.php
+++ b/actions/twitapidirect_messages.php
@@ -141,9 +141,10 @@ class Twitapidirect_messagesAction extends TwitterapiAction
$code = 406, $apidata['content-type']);
} else {
$content_shortened = common_shorten_links($content);
- if (mb_strlen($content_shortened) > 140) {
- $this->clientError(_('That\'s too long. Max message size is 140 chars.'),
- $code = 406, $apidata['content-type']);
+ if (Message::contentTooLong($content_shortened)) {
+ $this->clientError(sprintf(_('That\'s too long. Max message size is %d chars.'),
+ Message::maxContent()),
+ $code = 406, $apidata['content-type']);
return;
}
}
diff --git a/actions/twitapigroups.php b/actions/twitapigroups.php
index 82604ebff..bebc07fa1 100644
--- a/actions/twitapigroups.php
+++ b/actions/twitapigroups.php
@@ -51,6 +51,103 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
class TwitapigroupsAction extends TwitterapiAction
{
+ function list_groups($args, $apidata)
+ {
+ parent::handle($args);
+
+ common_debug("in groups api action");
+
+ $this->auth_user = $apidata['user'];
+ $user = $this->get_user($apidata['api_arg'], $apidata);
+
+ if (empty($user)) {
+ $this->clientError('Not Found', 404, $apidata['content-type']);
+ return;
+ }
+
+ $page = (int)$this->arg('page', 1);
+ $count = (int)$this->arg('count', 20);
+ $max_id = (int)$this->arg('max_id', 0);
+ $since_id = (int)$this->arg('since_id', 0);
+ $since = $this->arg('since');
+ $group = $user->getGroups(($page-1)*$count,
+ $count, $since_id, $max_id, $since);
+
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_("%s's groups"), $user->nickname);
+ $taguribase = common_config('integration', 'taguri');
+ $id = "tag:$taguribase:Groups";
+ $link = common_root_url();
+ $subtitle = sprintf(_("groups %s is a member of on %s"), $user->nickname, $sitename);
+
+ switch($apidata['content-type']) {
+ case 'xml':
+ $this->show_xml_groups($group);
+ break;
+ case 'rss':
+ $this->show_rss_groups($group, $title, $link, $subtitle);
+ break;
+ case 'atom':
+ $selfuri = common_root_url() . 'api/laconica/groups/list/' . $user->id . '.atom';
+ $this->show_atom_groups($group, $title, $id, $link,
+ $subtitle, $selfuri);
+ break;
+ case 'json':
+ $this->show_json_groups($group);
+ break;
+ default:
+ $this->clientError(_('API method not found!'), $code = 404);
+ break;
+ }
+ }
+
+ function list_all($args, $apidata)
+ {
+ parent::handle($args);
+
+ common_debug("in groups api action");
+
+ $page = (int)$this->arg('page', 1);
+ $count = (int)$this->arg('count', 20);
+ $max_id = (int)$this->arg('max_id', 0);
+ $since_id = (int)$this->arg('since_id', 0);
+ $since = $this->arg('since');
+
+ /* TODO:
+ Use the $page, $count, $max_id, $since_id, and $since parameters
+ */
+ $group = new User_group();
+ $group->orderBy('created DESC');
+ $group->find();
+
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_("%s groups"), $sitename);
+ $taguribase = common_config('integration', 'taguri');
+ $id = "tag:$taguribase:Groups";
+ $link = common_root_url();
+ $subtitle = sprintf(_("groups on %s"), $sitename);
+
+ switch($apidata['content-type']) {
+ case 'xml':
+ $this->show_xml_groups($group);
+ break;
+ case 'rss':
+ $this->show_rss_groups($group, $title, $link, $subtitle);
+ break;
+ case 'atom':
+ $selfuri = common_root_url() . 'api/laconica/groups/list_all.atom';
+ $this->show_atom_groups($group, $title, $id, $link,
+ $subtitle, $selfuri);
+ break;
+ case 'json':
+ $this->show_json_groups($group);
+ break;
+ default:
+ $this->clientError(_('API method not found!'), $code = 404);
+ break;
+ }
+ }
+
function show($args, $apidata)
{
parent::handle($args);
diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php
index e3d366ecc..1f3c53bef 100644
--- a/actions/twitapistatuses.php
+++ b/actions/twitapistatuses.php
@@ -242,14 +242,15 @@ class TwitapistatusesAction extends TwitterapiAction
$status_shortened = common_shorten_links($status);
- if (mb_strlen($status_shortened) > 140) {
+ if (Notice::contentTooLong($status_shortened)) {
// XXX: Twitter truncates anything over 140, flags the status
// as "truncated." Sending this error may screw up some clients
// that assume Twitter will truncate for them. Should we just
// truncate too? -- Zach
- $this->clientError(_('That\'s too long. Max notice size is 140 chars.'),
- $code = 406, $apidata['content-type']);
+ $this->clientError(sprintf(_('That\'s too long. Max notice size is %d chars.'),
+ Notice::maxContent()),
+ $code = 406, $apidata['content-type']);
return;
}
}
@@ -455,7 +456,8 @@ class TwitapistatusesAction extends TwitterapiAction
function friends($args, $apidata)
{
parent::handle($args);
- return $this->subscriptions($apidata, 'subscribed', 'subscriber');
+ $includeStatuses=! (boolean) $args['lite'];
+ return $this->subscriptions($apidata, 'subscribed', 'subscriber', false, $includeStatuses);
}
function friendsIDs($args, $apidata)
@@ -467,7 +469,8 @@ class TwitapistatusesAction extends TwitterapiAction
function followers($args, $apidata)
{
parent::handle($args);
- return $this->subscriptions($apidata, 'subscriber', 'subscribed');
+ $includeStatuses=! (boolean) $args['lite'];
+ return $this->subscriptions($apidata, 'subscriber', 'subscribed', false, $includeStatuses);
}
function followersIDs($args, $apidata)
@@ -476,7 +479,7 @@ class TwitapistatusesAction extends TwitterapiAction
return $this->subscriptions($apidata, 'subscriber', 'subscribed', true);
}
- function subscriptions($apidata, $other_attr, $user_attr, $onlyIDs=false)
+ function subscriptions($apidata, $other_attr, $user_attr, $onlyIDs=false, $includeStatuses=true)
{
$this->auth_user = $apidata['user'];
$user = $this->get_user($apidata['api_arg'], $apidata);
@@ -532,26 +535,26 @@ class TwitapistatusesAction extends TwitterapiAction
if ($onlyIDs) {
$this->showIDs($others, $type);
} else {
- $this->show_profiles($others, $type);
+ $this->show_profiles($others, $type, $includeStatuses);
}
$this->end_document($type);
}
- function show_profiles($profiles, $type)
+ function show_profiles($profiles, $type, $includeStatuses)
{
switch ($type) {
case 'xml':
$this->elementStart('users', array('type' => 'array'));
foreach ($profiles as $profile) {
- $this->show_profile($profile);
+ $this->show_profile($profile,$type,null,$includeStatuses);
}
$this->elementEnd('users');
break;
case 'json':
$arrays = array();
foreach ($profiles as $profile) {
- $arrays[] = $this->twitter_user_array($profile, true);
+ $arrays[] = $this->twitter_user_array($profile, $includeStatuses);
}
print json_encode($arrays);
break;
diff --git a/actions/twitterauthorization.php b/actions/twitterauthorization.php
new file mode 100644
index 000000000..b04f35327
--- /dev/null
+++ b/actions/twitterauthorization.php
@@ -0,0 +1,222 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Class for doing OAuth authentication against Twitter
+ *
+ * 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 Twitter
+ * @package Laconica
+ * @author Zach Copely <zach@controlyourself.ca>
+ * @copyright 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);
+}
+
+/**
+ * Class for doing OAuth authentication against Twitter
+ *
+ * Peforms the OAuth "dance" between Laconica and Twitter -- requests a token,
+ * authorizes it, and exchanges it for an access token. It also creates a link
+ * (Foreign_link) between the Laconica user and Twitter user and stores the
+ * access token and secret in the link.
+ *
+ * @category Twitter
+ * @package Laconica
+ * @author Zach Copley <zach@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 TwitterauthorizationAction extends Action
+{
+ /**
+ * Initialize class members. Looks for 'oauth_token' parameter.
+ *
+ * @param array $args misc. arguments
+ *
+ * @return boolean true
+ */
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->oauth_token = $this->arg('oauth_token');
+
+ return true;
+ }
+
+ /**
+ * Handler method
+ *
+ * @param array $args is ignored since it's now passed in in prepare()
+ *
+ * @return nothing
+ */
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (!common_logged_in()) {
+ $this->clientError(_('Not logged in.'), 403);
+ }
+
+ $user = common_current_user();
+ $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE);
+
+ // If there's already a foreign link record, it means we already
+ // have an access token, and this is unecessary. So go back.
+
+ if (isset($flink)) {
+ common_redirect(common_local_url('twittersettings'));
+ }
+
+ // $this->oauth_token is only populated once Twitter authorizes our
+ // request token. If it's empty we're at the beginning of the auth
+ // process
+
+ if (empty($this->oauth_token)) {
+ $this->authorizeRequestToken();
+ } else {
+ $this->saveAccessToken();
+ }
+ }
+
+ /**
+ * Asks Twitter for a request token, and then redirects to Twitter
+ * to authorize it.
+ *
+ * @return nothing
+ */
+ function authorizeRequestToken()
+ {
+ try {
+
+ // Get a new request token and authorize it
+
+ $client = new TwitterOAuthClient();
+ $req_tok =
+ $client->getRequestToken(TwitterOAuthClient::$requestTokenURL);
+
+ // Sock the request token away in the session temporarily
+
+ $_SESSION['twitter_request_token'] = $req_tok->key;
+ $_SESSION['twitter_request_token_secret'] = $req_tok->secret;
+
+ $auth_link = $client->getAuthorizeLink($req_tok);
+
+ } catch (TwitterOAuthClientException $e) {
+ $msg = sprintf('OAuth client cURL error - code: %1s, msg: %2s',
+ $e->getCode(), $e->getMessage());
+ $this->serverError(_('Couldn\'t link your Twitter account.'));
+ }
+
+ common_redirect($auth_link);
+ }
+
+ /**
+ * Called when Twitter returns an authorized request token. Exchanges
+ * it for an access token and stores it.
+ *
+ * @return nothing
+ */
+ function saveAccessToken()
+ {
+
+ // Check to make sure Twitter returned the same request
+ // token we sent them
+
+ if ($_SESSION['twitter_request_token'] != $this->oauth_token) {
+ $this->serverError(_('Couldn\'t link your Twitter account.'));
+ }
+
+ try {
+
+ $client = new TwitterOAuthClient($_SESSION['twitter_request_token'],
+ $_SESSION['twitter_request_token_secret']);
+
+ // Exchange the request token for an access token
+
+ $atok = $client->getAccessToken(TwitterOAuthClient::$accessTokenURL);
+
+ // Test the access token and get the user's Twitter info
+
+ $client = new TwitterOAuthClient($atok->key, $atok->secret);
+ $twitter_user = $client->verifyCredentials();
+
+ } catch (OAuthClientException $e) {
+ $msg = sprintf('OAuth client cURL error - code: %1$s, msg: %2$s',
+ $e->getCode(), $e->getMessage());
+ $this->serverError(_('Couldn\'t link your Twitter account.'));
+ }
+
+ // Save the access token and Twitter user info
+
+ $this->saveForeignLink($atok, $twitter_user);
+
+ // Clean up the the mess we made in the session
+
+ unset($_SESSION['twitter_request_token']);
+ unset($_SESSION['twitter_request_token_secret']);
+
+ common_redirect(common_local_url('twittersettings'));
+ }
+
+ /**
+ * Saves a Foreign_link between Twitter user and local user,
+ * which includes the access token and secret.
+ *
+ * @param OAuthToken $access_token the access token to save
+ * @param mixed $twitter_user twitter API user object
+ *
+ * @return nothing
+ */
+ function saveForeignLink($access_token, $twitter_user)
+ {
+ $user = common_current_user();
+
+ $flink = new Foreign_link();
+
+ $flink->user_id = $user->id;
+ $flink->foreign_id = $twitter_user->id;
+ $flink->service = TWITTER_SERVICE;
+
+ $creds = TwitterOAuthClient::packToken($access_token);
+
+ $flink->credentials = $creds;
+ $flink->created = common_sql_now();
+
+ // Defaults: noticesync on, everything else off
+
+ $flink->set_flags(true, false, false, false);
+
+ $flink_id = $flink->insert();
+
+ if (empty($flink_id)) {
+ common_log_db_error($flink, 'INSERT', __FILE__);
+ $this->serverError(_('Couldn\'t link your Twitter account.'));
+ }
+
+ save_twitter_user($twitter_user->id, $twitter_user->screen_name);
+ }
+
+}
+
diff --git a/actions/twittersettings.php b/actions/twittersettings.php
index 2b742788e..0859ab9d3 100644
--- a/actions/twittersettings.php
+++ b/actions/twittersettings.php
@@ -34,8 +34,6 @@ if (!defined('LACONICA')) {
require_once INSTALLDIR.'/lib/connectsettingsaction.php';
require_once INSTALLDIR.'/lib/twitter.php';
-define('SUBSCRIPTIONS', 80);
-
/**
* Settings for Twitter integration
*
@@ -69,9 +67,8 @@ class TwittersettingsAction extends ConnectSettingsAction
function getInstructions()
{
- return _('Add your Twitter account to automatically send '.
- ' your notices to Twitter, ' .
- 'and subscribe to Twitter friends already here.');
+ return _('Connect your Twitter account to share your updates ' .
+ 'with your Twitter friends and vice-versa.');
}
/**
@@ -85,6 +82,12 @@ class TwittersettingsAction extends ConnectSettingsAction
function showContent()
{
+ if (!common_config('twitter', 'enabled')) {
+ $this->element('div', array('class' => 'error'),
+ _('Twitter is not available.'));
+ return;
+ }
+
$user = common_current_user();
$profile = $user->getProfile();
@@ -93,7 +96,7 @@ class TwittersettingsAction extends ConnectSettingsAction
$flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE);
- if ($flink) {
+ if (!empty($flink)) {
$fuser = $flink->getForeignUser();
}
@@ -102,192 +105,86 @@ class TwittersettingsAction extends ConnectSettingsAction
'class' => 'form_settings',
'action' =>
common_local_url('twittersettings')));
- $this->elementStart('fieldset', array('id' => 'settings_twitter_account'));
- $this->element('legend', null, _('Twitter Account'));
+
$this->hidden('token', common_session_token());
- if ($fuser) {
+
+ $this->elementStart('fieldset', array('id' => 'settings_twitter_account'));
+
+ if (empty($fuser)) {
$this->elementStart('ul', 'form_data');
- $this->elementStart('li', array('id' => 'settings_twitter_remove'));
- $this->element('span', 'twitter_user', $fuser->nickname);
- $this->element('a', array('href' => $fuser->uri), $fuser->uri);
- $this->element('p', 'form_note',
- _('Current verified Twitter account.'));
- $this->hidden('flink_foreign_id', $flink->foreign_id);
+ $this->elementStart('li', array('id' => 'settings_twitter_login_button'));
+ $this->element('a', array('href' => common_local_url('twitterauthorization')),
+ 'Connect my Twitter account');
$this->elementEnd('li');
$this->elementEnd('ul');
- $this->submit('remove', _('Remove'));
+
+ $this->elementEnd('fieldset');
} else {
+ $this->element('legend', null, _('Twitter account'));
+ $this->elementStart('p', array('id' => 'form_confirmed'));
+ $this->element('a', array('href' => $fuser->uri), $fuser->nickname);
+ $this->elementEnd('p');
+ $this->element('p', 'form_note',
+ _('Connected Twitter account'));
+
+ $this->submit('remove', _('Remove'));
+
+ $this->elementEnd('fieldset');
+
+ $this->elementStart('fieldset', array('id' => 'settings_twitter_preferences'));
+
+ $this->element('legend', null, _('Preferences'));
$this->elementStart('ul', 'form_data');
- $this->elementStart('li', array('id' => 'settings_twitter_login'));
- $this->input('twitter_username', _('Twitter user name'),
- ($this->arg('twitter_username')) ?
- $this->arg('twitter_username') :
- $profile->nickname,
- _('No spaces, please.')); // hey, it's what Twitter says
+ $this->elementStart('li');
+ $this->checkbox('noticesend',
+ _('Automatically send my notices to Twitter.'),
+ ($flink) ?
+ ($flink->noticesync & FOREIGN_NOTICE_SEND) :
+ true);
$this->elementEnd('li');
$this->elementStart('li');
- $this->password('twitter_password', _('Twitter password'));
- $this->elementend('li');
- $this->elementEnd('ul');
- }
- $this->elementEnd('fieldset');
-
- $this->elementStart('fieldset',
- array('id' => 'settings_twitter_preferences'));
- $this->element('legend', null, _('Preferences'));
-
- $this->elementStart('ul', 'form_data');
- $this->elementStart('li');
- $this->checkbox('noticesend',
- _('Automatically send my notices to Twitter.'),
- ($flink) ?
- ($flink->noticesync & FOREIGN_NOTICE_SEND) :
- true);
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->checkbox('replysync',
- _('Send local "@" replies to Twitter.'),
- ($flink) ?
- ($flink->noticesync & FOREIGN_NOTICE_SEND_REPLY) :
- true);
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->checkbox('friendsync',
- _('Subscribe to my Twitter friends here.'),
- ($flink) ?
- ($flink->friendsync & FOREIGN_FRIEND_RECV) :
- false);
- $this->elementEnd('li');
-
- if (common_config('twitterbridge','enabled')) {
+ $this->checkbox('replysync',
+ _('Send local "@" replies to Twitter.'),
+ ($flink) ?
+ ($flink->noticesync & FOREIGN_NOTICE_SEND_REPLY) :
+ true);
+ $this->elementEnd('li');
$this->elementStart('li');
- $this->checkbox('noticerecv',
- _('Import my Friends Timeline.'),
+ $this->checkbox('friendsync',
+ _('Subscribe to my Twitter friends here.'),
($flink) ?
- ($flink->noticesync & FOREIGN_NOTICE_RECV) :
+ ($flink->friendsync & FOREIGN_FRIEND_RECV) :
false);
$this->elementEnd('li');
- } else {
- // preserve setting even if bidrection bridge toggled off
- if ($flink && ($flink->noticesync & FOREIGN_NOTICE_RECV)) {
- $this->hidden('noticerecv', true, 'noticerecv');
- }
- }
-
- $this->elementEnd('ul');
-
- if ($flink) {
- $this->submit('save', _('Save'));
- } else {
- $this->submit('add', _('Add'));
- }
- $this->elementEnd('fieldset');
-
- $this->showTwitterSubscriptions();
-
- $this->elementEnd('form');
- }
-
- /**
- * Gets some of the user's Twitter friends
- *
- * Gets the number of Twitter friends that are on this
- * instance of Laconica.
- *
- * @return array array of User objects
- */
-
- function subscribedTwitterUsers()
- {
-
- $current_user = common_current_user();
-
- $qry = 'SELECT "user".* ' .
- 'FROM subscription ' .
- 'JOIN "user" ON subscription.subscribed = "user".id ' .
- 'JOIN foreign_link ON foreign_link.user_id = "user".id ' .
- 'WHERE subscriber = %d ' .
- 'ORDER BY "user".nickname';
-
- $user = new User();
-
- $user->query(sprintf($qry, $current_user->id));
-
- $users = array();
-
- while ($user->fetch()) {
-
- // Don't include the user's own self-subscription
- if ($user->id != $current_user->id) {
- $users[] = clone($user);
- }
- }
-
- return $users;
- }
-
- /**
- * Show user's Twitter friends
- *
- * Gets the number of Twitter friends that are on this
- * instance of Laconica, and shows their mini-avatars.
- *
- * @return void
- */
-
- function showTwitterSubscriptions()
- {
-
- $friends = $this->subscribedTwitterUsers();
-
- $friends_count = count($friends);
- if ($friends_count > 0) {
- $this->elementStart('div', array('id' => 'entity_subscriptions',
- 'class' => 'section'));
- $this->element('h2', null, _('Twitter Friends'));
- $this->elementStart('ul', 'entities users xoxo');
-
- for ($i = 0; $i < min($friends_count, SUBSCRIPTIONS); $i++) {
+ if (common_config('twitterbridge','enabled')) {
+ $this->elementStart('li');
+ $this->checkbox('noticerecv',
+ _('Import my Friends Timeline.'),
+ ($flink) ?
+ ($flink->noticesync & FOREIGN_NOTICE_RECV) :
+ false);
+ $this->elementEnd('li');
- $other = Profile::staticGet($friends[$i]->id);
+ // preserve setting even if bidrection bridge toggled off
- if (!$other) {
- common_log_db_error($subs, 'SELECT', __FILE__);
- continue;
+ if ($flink && ($flink->noticesync & FOREIGN_NOTICE_RECV)) {
+ $this->hidden('noticerecv', true, 'noticerecv');
}
-
- $this->elementStart('li', 'vcard');
- $this->elementStart('a', array('title' => ($other->fullname) ?
- $other->fullname :
- $other->nickname,
- 'href' => $other->profileurl,
- 'class' => 'url'));
-
- $avatar = $other->getAvatar(AVATAR_MINI_SIZE);
-
- $avatar_url = ($avatar) ?
- $avatar->displayUrl() :
- Avatar::defaultImage(AVATAR_MINI_SIZE);
-
- $this->element('img', array('src' => $avatar_url,
- 'width' => AVATAR_MINI_SIZE,
- 'height' => AVATAR_MINI_SIZE,
- 'class' => 'avatar photo',
- 'alt' => ($other->fullname) ?
- $other->fullname :
- $other->nickname));
-
- $this->element('span', 'fn nickname', $other->nickname);
- $this->elementEnd('a');
- $this->elementEnd('li');
-
}
$this->elementEnd('ul');
- $this->elementEnd('div');
+ if ($flink) {
+ $this->submit('save', _('Save'));
+ } else {
+ $this->submit('add', _('Add'));
+ }
+
+ $this->elementEnd('fieldset');
}
+
+ $this->elementEnd('form');
}
/**
@@ -303,7 +200,6 @@ class TwittersettingsAction extends ConnectSettingsAction
function handlePost()
{
-
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
@@ -314,8 +210,6 @@ class TwittersettingsAction extends ConnectSettingsAction
if ($this->arg('save')) {
$this->savePreferences();
- } else if ($this->arg('add')) {
- $this->addTwitterAccount();
} else if ($this->arg('remove')) {
$this->removeTwitterAccount();
} else {
@@ -324,82 +218,6 @@ class TwittersettingsAction extends ConnectSettingsAction
}
/**
- * Associate a Twitter account with the user's account
- *
- * Validates post input; verifies it against Twitter; and if
- * successful stores in the database.
- *
- * @return void
- */
-
- function addTwitterAccount()
- {
- $screen_name = $this->trimmed('twitter_username');
- $password = $this->trimmed('twitter_password');
- $noticesend = $this->boolean('noticesend');
- $noticerecv = $this->boolean('noticerecv');
- $replysync = $this->boolean('replysync');
- $friendsync = $this->boolean('friendsync');
-
- if (!Validate::string($screen_name,
- array('min_length' => 1,
- 'max_length' => 15,
- 'format' => VALIDATE_NUM.VALIDATE_ALPHA.'_'))) {
- $this->showForm(_('Username must have only numbers, '.
- 'upper- and lowercase letters, '.
- 'and underscore (_). 15 chars max.'));
- return;
- }
-
- if (!$this->verifyCredentials($screen_name, $password)) {
- $this->showForm(_('Could not verify your Twitter credentials!'));
- return;
- }
-
- $twit_user = twitter_user_info($screen_name, $password);
-
- if (!$twit_user) {
- $this->showForm(sprintf(_('Unable to retrieve account information '.
- 'For "%s" from Twitter.'),
- $screen_name));
- return;
- }
-
- if (!save_twitter_user($twit_user->id, $screen_name)) {
- $this->showForm(_('Unable to save your Twitter settings!'));
- return;
- }
-
- $user = common_current_user();
-
- $flink = new Foreign_link();
-
- $flink->user_id = $user->id;
- $flink->foreign_id = $twit_user->id;
- $flink->service = TWITTER_SERVICE;
- $flink->credentials = $password;
- $flink->created = common_sql_now();
-
- $flink->set_flags($noticesend, $noticerecv, $replysync, $friendsync);
-
- $flink_id = $flink->insert();
-
- if (!$flink_id) {
- common_log_db_error($flink, 'INSERT', __FILE__);
- $this->showForm(_('Unable to save your Twitter settings!'));
- return;
- }
-
- if ($friendsync) {
- save_twitter_friends($user, $twit_user->id, $screen_name, $password);
- $flink->last_friendsync = common_sql_now();
- $flink->update();
- }
-
- $this->showForm(_('Twitter settings saved.'), true);
- }
-
- /**
* Disassociate an existing Twitter account from this account
*
* @return void
@@ -408,20 +226,11 @@ class TwittersettingsAction extends ConnectSettingsAction
function removeTwitterAccount()
{
$user = common_current_user();
-
- $flink = Foreign_link::getByUserID($user->id, 1);
-
- $flink_foreign_id = $this->arg('flink_foreign_id');
-
- // Maybe an old tab open...?
- if ($flink->foreign_id != $flink_foreign_id) {
- $this->showForm(_('That is not your Twitter account.'));
- return;
- }
+ $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE);
$result = $flink->delete();
- if (!$result) {
+ if (empty($result)) {
common_log_db_error($flink, 'DELETE', __FILE__);
$this->serverError(_('Couldn\'t remove Twitter user.'));
return;
@@ -444,32 +253,16 @@ class TwittersettingsAction extends ConnectSettingsAction
$replysync = $this->boolean('replysync');
$user = common_current_user();
+ $flink = Foreign_link::getByUserID($user->id, TWITTER_SERVICE);
- $flink = Foreign_link::getByUserID($user->id, 1);
-
- if (!$flink) {
+ if (empty($flink)) {
common_log_db_error($flink, 'SELECT', __FILE__);
$this->showForm(_('Couldn\'t save Twitter preferences.'));
return;
}
- $twitter_id = $flink->foreign_id;
- $password = $flink->credentials;
-
- $fuser = $flink->getForeignUser();
-
- if (!$fuser) {
- common_log_db_error($fuser, 'SELECT', __FILE__);
- $this->showForm(_('Couldn\'t save Twitter preferences.'));
- return;
- }
-
- $screen_name = $fuser->nickname;
-
$original = clone($flink);
-
$flink->set_flags($noticesend, $noticerecv, $replysync, $friendsync);
-
$result = $flink->update($original);
if ($result === false) {
@@ -478,45 +271,7 @@ class TwittersettingsAction extends ConnectSettingsAction
return;
}
- if ($friendsync) {
- save_twitter_friends($user, $flink->foreign_id, $screen_name, $password);
- }
-
$this->showForm(_('Twitter preferences saved.'), true);
}
- /**
- * Verifies a username and password against Twitter's API
- *
- * @param string $screen_name Twitter user name
- * @param string $password Twitter password
- *
- * @return boolean success flag
- */
-
- function verifyCredentials($screen_name, $password)
- {
- $uri = 'http://twitter.com/account/verify_credentials.json';
-
- $data = get_twitter_data($uri, $screen_name, $password);
-
- if (!$data) {
- return false;
- }
-
- $user = json_decode($data);
-
- if (!$user) {
- return false;
- }
-
- $twitter_id = $user->id;
-
- if ($twitter_id) {
- return $twitter_id;
- }
-
- return false;
- }
-
}
diff --git a/actions/unsubscribe.php b/actions/unsubscribe.php
index 19275041a..46fbcf657 100644
--- a/actions/unsubscribe.php
+++ b/actions/unsubscribe.php
@@ -1,5 +1,16 @@
<?php
-/*
+/**
+ * Unsubscribe handler
+ *
+ * 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.
*
@@ -17,6 +28,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Unsubscribe handler
+ *
+ * @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 UnsubscribeAction extends Action
{
@@ -31,16 +56,18 @@ class UnsubscribeAction extends Action
$user = common_current_user();
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
- common_redirect(common_local_url('subscriptions', array('nickname' => $user->nickname)));
+ common_redirect(common_local_url('subscriptions',
+ array('nickname' => $user->nickname)));
return;
}
- # CSRF protection
+ /* Use a session token for CSRF protection. */
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
- $this->clientError(_('There was a problem with your session token. Try again, please.'));
+ $this->clientError(_('There was a problem with your session token. ' .
+ 'Try again, please.'));
return;
}
@@ -53,7 +80,7 @@ class UnsubscribeAction extends Action
$other = Profile::staticGet('id', $other_id);
- if (!$other_id) {
+ if (!$other) {
$this->clientError(_('No profile with that id.'));
return;
}
@@ -76,8 +103,8 @@ class UnsubscribeAction extends Action
$this->elementEnd('body');
$this->elementEnd('html');
} else {
- common_redirect(common_local_url('subscriptions', array('nickname' =>
- $user->nickname)),
+ common_redirect(common_local_url('subscriptions',
+ array('nickname' => $user->nickname)),
303);
}
}
diff --git a/actions/updateprofile.php b/actions/updateprofile.php
index d8b62fb09..b020413b3 100644
--- a/actions/updateprofile.php
+++ b/actions/updateprofile.php
@@ -1,5 +1,16 @@
<?php
-/*
+/**
+ * Handle an updateprofile action
+ *
+ * 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.
*
@@ -17,34 +28,34 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
-require_once(INSTALLDIR.'/lib/omb.php');
+require_once INSTALLDIR.'/lib/omb.php';
+require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
+/**
+ * Handle an updateprofile action
+ *
+ * @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 UpdateprofileAction extends Action
{
-
- function handle($args)
- {
- parent::handle($args);
- try {
- common_remove_magic_from_request();
- $req = OAuthRequest::from_request('POST', common_local_url('updateprofile'));
- # Note: server-to-server function!
- $server = omb_oauth_server();
- list($consumer, $token) = $server->verify_request($req);
- if ($this->update_profile($req, $consumer, $token)) {
- header('HTTP/1.1 200 OK');
- header('Content-type: text/plain');
- print "omb_version=".OMB_VERSION_01;
- }
- } catch (OAuthException $e) {
- $this->serverError($e->getMessage());
- return;
- }
- }
- function update_profile($req, $consumer, $token)
+ /**
+ * For initializing members of the class.
+ *
+ * @param array $argarray misc. arguments
+ *
+ * @return boolean true
+ */
+ function prepare($argarray)
{
$version = $req->get_parameter('omb_version');
if ($version != OMB_VERSION_01) {
@@ -79,7 +90,7 @@ class UpdateprofileAction extends Action
$nickname = $req->get_parameter('omb_listenee_nickname');
if ($nickname && !Validate::string($nickname, array('min_length' => 1,
'max_length' => 64,
- 'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
+ 'format' => NICKNAME_FMT))) {
$this->clientError(_('Nickname must have only lowercase letters and numbers and no spaces.'));
return false;
}
@@ -88,96 +99,20 @@ class UpdateprofileAction extends Action
$this->clientError(sprintf(_("Invalid license URL '%s'"), $license));
return false;
}
- $profile_url = $req->get_parameter('omb_listenee_profile');
- if ($profile_url && !common_valid_http_url($profile_url)) {
- $this->clientError(sprintf(_("Invalid profile URL '%s'."), $profile_url));
- return false;
- }
- # optional stuff
- $fullname = $req->get_parameter('omb_listenee_fullname');
- if ($fullname && mb_strlen($fullname) > 255) {
- $this->clientError(_("Full name is too long (max 255 chars)."));
- return false;
- }
- $homepage = $req->get_parameter('omb_listenee_homepage');
- if ($homepage && (!common_valid_http_url($homepage) || mb_strlen($homepage) > 255)) {
- $this->clientError(sprintf(_("Invalid homepage '%s'"), $homepage));
- return false;
- }
- $bio = $req->get_parameter('omb_listenee_bio');
- if ($bio && mb_strlen($bio) > 140) {
- $this->clientError(_("Bio is too long (max 140 chars)."));
- return false;
- }
- $location = $req->get_parameter('omb_listenee_location');
- if ($location && mb_strlen($location) > 255) {
- $this->clientError(_("Location is too long (max 255 chars)."));
- return false;
- }
- $avatar = $req->get_parameter('omb_listenee_avatar');
- if ($avatar) {
- if (!common_valid_http_url($avatar) || strlen($avatar) > 255) {
- $this->clientError(sprintf(_("Invalid avatar URL '%s'"), $avatar));
- return false;
- }
- $size = @getimagesize($avatar);
- if (!$size) {
- $this->clientError(sprintf(_("Can't read avatar URL '%s'"), $avatar));
- return false;
- }
- if ($size[0] != AVATAR_PROFILE_SIZE || $size[1] != AVATAR_PROFILE_SIZE) {
- $this->clientError(sprintf(_("Wrong size image at '%s'"), $avatar));
- return false;
- }
- if (!in_array($size[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG,
- IMAGETYPE_PNG))) {
- $this->clientError(sprintf(_("Wrong image type for '%s'"), $avatar));
- return false;
- }
- }
-
- $orig_profile = clone($profile);
+ return true;
+ }
- /* Use values even if they are an empty string. Parsing an empty string in
- updateProfile is the specified way of clearing a parameter in OMB. */
- if (!is_null($nickname)) {
- $profile->nickname = $nickname;
- }
- if (!is_null($profile_url)) {
- $profile->profileurl = $profile_url;
- }
- if (!is_null($fullname)) {
- $profile->fullname = $fullname;
- }
- if (!is_null($homepage)) {
- $profile->homepage = $homepage;
- }
- if (!is_null($bio)) {
- $profile->bio = $bio;
- }
- if (!is_null($location)) {
- $profile->location = $location;
- }
+ function handle($args)
+ {
+ parent::handle($args);
- if (!$profile->update($orig_profile)) {
- $this->serverError(_('Could not save new profile info'), 500);
- return false;
- } else {
- if ($avatar) {
- $temp_filename = tempnam(sys_get_temp_dir(), 'listenee_avatar');
- copy($avatar, $temp_filename);
- $imagefile = new ImageFile($profile->id, $temp_filename);
- $filename = Avatar::filename($profile->id,
- image_type_to_extension($imagefile->type),
- null,
- common_timestamp());
- rename($temp_filename, Avatar::path($filename));
- if (!$profile->setOriginal($filename)) {
- $this->serverError(_('Could not save avatar info'), 500);
- return false;
- }
- }
- return true;
+ try {
+ $srv = new OMB_Service_Provider(null, omb_oauth_datastore(),
+ omb_oauth_server());
+ $srv->handleUpdateProfile();
+ } catch (Exception $e) {
+ $this->serverError($e->getMessage());
+ return;
}
}
-}
+} \ No newline at end of file
diff --git a/actions/userauthorization.php b/actions/userauthorization.php
index 8dc2c808d..3e7be9747 100644
--- a/actions/userauthorization.php
+++ b/actions/userauthorization.php
@@ -1,5 +1,16 @@
<?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.
*
@@ -17,9 +28,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('LACONICA')) {
+ exit(1);
+}
-require_once(INSTALLDIR.'/lib/omb.php');
+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
@@ -32,42 +47,62 @@ class UserauthorizationAction extends Action
parent::handle($args);
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
- # CSRF protection
+ /* Use a session token for CSRF protection. */
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
- $params = $this->getStoredParams();
- $this->showForm($params, _('There was a problem with your session token. '.
- 'Try again, please.'));
+ $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
+ /* We've shown the form, now post user's choice. */
$this->sendAuthorization();
} else {
if (!common_logged_in()) {
- # Go log in, and then come back
+ /* Go log in, and then come back. */
common_set_returnto($_SERVER['REQUEST_URI']);
- common_redirect(common_local_url('login'));
+ if (!common_config('site', 'openidonly')) {
+ common_redirect(common_local_url('login'));
+ } else {
+ common_redirect(common_local_url('openidlogin'));
+ }
+ 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->validateRequest();
- $this->storeParams($_GET);
- $this->showForm($_GET);
- } catch (OAuthException $e) {
+ $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->error = $error;
$this->showPage();
}
@@ -79,23 +114,24 @@ class UserauthorizationAction extends Action
function showPageNotice()
{
$this->element('p', null, _('Please check these details to make sure '.
- 'that you want to subscribe to this user\'s notices. '.
- 'If you didn\'t just ask to subscribe to someone\'s notices, '.
- 'click "Reject".'));
+ 'that you want to subscribe to this ' .
+ 'user’s notices. If you didn’t just ask ' .
+ 'to subscribe to someone’s notices, '.
+ 'click “Reject”.'));
}
function showContent()
{
$params = $this->params;
- $nickname = $params['omb_listenee_nickname'];
- $profile = $params['omb_listenee_profile'];
- $license = $params['omb_listenee_license'];
- $fullname = $params['omb_listenee_fullname'];
- $homepage = $params['omb_listenee_homepage'];
- $bio = $params['omb_listenee_bio'];
- $location = $params['omb_listenee_location'];
- $avatar = $params['omb_listenee_avatar'];
+ $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');
@@ -172,11 +208,14 @@ class UserauthorizationAction extends Action
'id' => 'userauthorization',
'class' => 'form_user_authorization',
'name' => 'userauthorization',
- 'action' => common_local_url('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->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');
@@ -186,191 +225,27 @@ class UserauthorizationAction extends Action
function sendAuthorization()
{
- $params = $this->getStoredParams();
+ $srv = $this->getStoredParams();
- if (!$params) {
+ if (is_null($srv)) {
$this->clientError(_('No authorization request!'));
return;
}
- $callback = $params['oauth_callback'];
-
- if ($this->arg('accept')) {
- if (!$this->authorizeToken($params)) {
- $this->clientError(_('Error authorizing token'));
- }
- if (!$this->saveRemoteProfile($params)) {
- $this->clientError(_('Error saving remote profile'));
- }
- if (!$callback) {
- $this->showAcceptMessage($params['oauth_token']);
- } else {
- $newparams = array();
- $newparams['oauth_token'] = $params['oauth_token'];
- $newparams['omb_version'] = OMB_VERSION_01;
- $user = User::staticGet('uri', $params['omb_listener']);
- $profile = $user->getProfile();
- if (!$profile) {
- common_log_db_error($user, 'SELECT', __FILE__);
- $this->serverError(_('User without matching profile'));
- return;
- }
- $newparams['omb_listener_nickname'] = $user->nickname;
- $newparams['omb_listener_profile'] = common_local_url('showstream',
- array('nickname' => $user->nickname));
- if (!is_null($profile->fullname)) {
- $newparams['omb_listener_fullname'] = $profile->fullname;
- }
- if (!is_null($profile->homepage)) {
- $newparams['omb_listener_homepage'] = $profile->homepage;
- }
- if (!is_null($profile->bio)) {
- $newparams['omb_listener_bio'] = $profile->bio;
- }
- if (!is_null($profile->location)) {
- $newparams['omb_listener_location'] = $profile->location;
- }
- $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
- if ($avatar) {
- $newparams['omb_listener_avatar'] = $avatar->url;
- }
- $parts = array();
- foreach ($newparams as $k => $v) {
- $parts[] = $k . '=' . OAuthUtil::urlencode_rfc3986($v);
- }
- $query_string = implode('&', $parts);
- $parsed = parse_url($callback);
- $url = $callback . (($parsed['query']) ? '&' : '?') . $query_string;
- common_redirect($url, 303);
- }
- } else {
- if (!$callback) {
- $this->showRejectMessage();
- } else {
- # XXX: not 100% sure how to signal failure... just redirect without token?
- common_redirect($callback, 303);
- }
- }
- }
-
- function authorizeToken(&$params)
- {
- $token_field = $params['oauth_token'];
- $rt = new Token();
- $rt->tok = $token_field;
- $rt->type = 0;
- $rt->state = 0;
- if ($rt->find(true)) {
- $orig_rt = clone($rt);
- $rt->state = 1; # Authorized but not used
- if ($rt->update($orig_rt)) {
- return true;
- }
- }
- return false;
- }
-
- # XXX: refactor with similar code in finishremotesubscribe.php
-
- function saveRemoteProfile(&$params)
- {
- # FIXME: we should really do this when the consumer comes
- # back for an access token. If they never do, we've got stuff in a
- # weird state.
-
- $nickname = $params['omb_listenee_nickname'];
- $fullname = $params['omb_listenee_fullname'];
- $profile_url = $params['omb_listenee_profile'];
- $homepage = $params['omb_listenee_homepage'];
- $bio = $params['omb_listenee_bio'];
- $location = $params['omb_listenee_location'];
- $avatar_url = $params['omb_listenee_avatar'];
-
- $listenee = $params['omb_listenee'];
- $remote = Remote_profile::staticGet('uri', $listenee);
-
- if ($remote) {
- $exists = true;
- $profile = Profile::staticGet($remote->id);
- $orig_remote = clone($remote);
- $orig_profile = clone($profile);
- } else {
- $exists = false;
- $remote = new Remote_profile();
- $remote->uri = $listenee;
- $profile = new Profile();
- }
-
- $profile->nickname = $nickname;
- $profile->profileurl = $profile_url;
-
- if (!is_null($fullname)) {
- $profile->fullname = $fullname;
- }
- if (!is_null($homepage)) {
- $profile->homepage = $homepage;
- }
- if (!is_null($bio)) {
- $profile->bio = $bio;
- }
- if (!is_null($location)) {
- $profile->location = $location;
- }
-
- if ($exists) {
- $profile->update($orig_profile);
- } else {
- $profile->created = DB_DataObject_Cast::dateTime(); # current time
- $id = $profile->insert();
- if (!$id) {
- return false;
- }
- $remote->id = $id;
+ $accepted = $this->arg('accept');
+ try {
+ list($val, $token) = $srv->continueUserAuth($accepted);
+ } catch (Exception $e) {
+ $this->clientError($e->getMessage());
+ return;
}
-
- if ($exists) {
- if (!$remote->update($orig_remote)) {
- return false;
- }
+ if ($val !== false) {
+ common_redirect($val, 303);
+ } elseif ($accepted) {
+ $this->showAcceptMessage($token);
} else {
- $remote->created = DB_DataObject_Cast::dateTime(); # current time
- if (!$remote->insert()) {
- return false;
- }
- }
-
- if ($avatar_url) {
- if (!$this->addAvatar($profile, $avatar_url)) {
- return false;
- }
- }
-
- $user = common_current_user();
-
- $sub = new Subscription();
- $sub->subscriber = $user->id;
- $sub->subscribed = $remote->id;
- $sub->token = $params['oauth_token']; # NOTE: request token, not valid for use!
- $sub->created = DB_DataObject_Cast::dateTime(); # current time
-
- if (!$sub->insert()) {
- return false;
+ $this->showRejectMessage();
}
-
- return true;
- }
-
- function addAvatar($profile, $url)
- {
- $temp_filename = tempnam(sys_get_temp_dir(), 'listenee_avatar');
- copy($url, $temp_filename);
- $imagefile = new ImageFile($profile->id, $temp_filename);
- $filename = Avatar::filename($profile->id,
- image_type_to_extension($imagefile->type),
- null,
- common_timestamp());
- rename($temp_filename, Avatar::path($filename));
- return $profile->setOriginal($filename);
}
function showAcceptMessage($tok)
@@ -378,26 +253,28 @@ class UserauthorizationAction extends Action
common_show_header(_('Subscription authorized'));
$this->element('p', null,
_('The subscription has been authorized, but no '.
- 'callback URL was passed. Check with the site\'s instructions for '.
- 'details on how to authorize the subscription. Your subscription token is:'));
+ 'callback URL was passed. Check with the site’s ' .
+ 'instructions for details on how to authorize the ' .
+ 'subscription. Your subscription token is:'));
$this->element('blockquote', 'token', $tok);
common_show_footer();
}
- function showRejectMessage($tok)
+ 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 site\'s instructions for '.
- 'details on how to fully reject the subscription.'));
+ 'callback URL was passed. Check with the site’s ' .
+ 'instructions for details on how to fully reject ' .
+ 'the subscription.'));
common_show_footer();
}
function storeParams($params)
{
common_ensure_session();
- $_SESSION['userauthorizationparams'] = $params;
+ $_SESSION['userauthorizationparams'] = serialize($params);
}
function clearParams()
@@ -409,138 +286,74 @@ class UserauthorizationAction extends Action
function getStoredParams()
{
common_ensure_session();
- $params = $_SESSION['userauthorizationparams'];
+ $params = unserialize($_SESSION['userauthorizationparams']);
return $params;
}
- # Throws an OAuthException if anything goes wrong
-
- function validateRequest()
- {
- /* Find token.
- TODO: If no token is passed the user should get a prompt to enter it
- according to OAuth Core 1.0 */
- $t = new Token();
- $t->tok = $_GET['oauth_token'];
- $t->type = 0;
- if (!$t->find(true)) {
- throw new OAuthException("Invalid request token: " . $_GET['oauth_token']);
- }
-
- $this->validateOmb();
- return true;
- }
-
function validateOmb()
{
- foreach (array('omb_version', 'omb_listener', 'omb_listenee',
- 'omb_listenee_profile', 'omb_listenee_nickname',
- 'omb_listenee_license') as $param)
- {
- if (!isset($_GET[$param]) || is_null($_GET[$param])) {
- throw new OAuthException("Required parameter '$param' not found");
- }
- }
- # Now, OMB stuff
- $version = $_GET['omb_version'];
- if ($version != OMB_VERSION_01) {
- throw new OAuthException("OpenMicroBlogging version '$version' not supported");
- }
$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 OAuthException("Listener URI '$listener' not found here");
- }
- $cur = common_current_user();
- if ($cur->id != $user->id) {
- throw new OAuthException("Can't add for another user!");
- }
- $listenee = $_GET['omb_listenee'];
- if (!Validate::uri($listenee) &&
- !common_valid_tag($listenee)) {
- throw new OAuthException("Listenee URI '$listenee' not a recognizable URI");
+ throw new Exception(sprintf(_('Listener URI ‘%s’ not found here'),
+ $listener));
}
+
if (strlen($listenee) > 255) {
- throw new OAuthException("Listenee URI '$listenee' too long");
+ throw new Exception(sprintf(_('Listenee URI ‘%s’ is too long.'),
+ $listenee));
}
$other = User::staticGet('uri', $listenee);
if ($other) {
- throw new OAuthException("Listenee URI '$listenee' is local user");
+ throw new Exception(sprintf(_('Listenee URI ‘%s’ is a local user.'),
+ $listenee));
}
$remote = Remote_profile::staticGet('uri', $listenee);
if ($remote) {
- $sub = new Subscription();
+ $sub = new Subscription();
$sub->subscriber = $user->id;
$sub->subscribed = $remote->id;
if ($sub->find(true)) {
- throw new OAuthException("Already subscribed to user!");
+ throw new Exception('You are already subscribed to this user.');
}
}
- $nickname = $_GET['omb_listenee_nickname'];
- if (!Validate::string($nickname, array('min_length' => 1,
- 'max_length' => 64,
- 'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
- throw new OAuthException('Nickname must have only letters and numbers and no spaces.');
- }
- $profile = $_GET['omb_listenee_profile'];
- if (!common_valid_http_url($profile)) {
- throw new OAuthException("Invalid profile URL '$profile'.");
- }
- if ($profile == common_local_url('showstream', array('nickname' => $nickname))) {
- throw new OAuthException("Profile URL '$profile' is for a local 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'];
- if (!common_valid_http_url($license)) {
- throw new OAuthException("Invalid license URL '$license'.");
}
+
+ $license = $_GET['omb_listenee_license'];
$site_license = common_config('license', 'url');
if (!common_compatible_license($license, $site_license)) {
- throw new OAuthException("Listenee stream license '$license' not compatible with site license '$site_license'.");
- }
- # optional stuff
- $fullname = $_GET['omb_listenee_fullname'];
- if ($fullname && mb_strlen($fullname) > 255) {
- throw new OAuthException("Full name '$fullname' too long.");
- }
- $homepage = $_GET['omb_listenee_homepage'];
- if ($homepage && (!common_valid_http_url($homepage) || mb_strlen($homepage) > 255)) {
- throw new OAuthException("Invalid homepage '$homepage'");
- }
- $bio = $_GET['omb_listenee_bio'];
- if ($bio && mb_strlen($bio) > 140) {
- throw new OAuthException("Bio too long '$bio'");
- }
- $location = $_GET['omb_listenee_location'];
- if ($location && mb_strlen($location) > 255) {
- throw new OAuthException("Location too long '$location'");
+ 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 OAuthException("Invalid avatar URL '$avatar'");
+ throw new Exception(sprintf(_('Avatar URL ‘%s’ is not valid.'),
+ $avatar));
}
$size = @getimagesize($avatar);
if (!$size) {
- throw new OAuthException("Can't read avatar URL '$avatar'");
- }
- if ($size[0] != AVATAR_PROFILE_SIZE || $size[1] != AVATAR_PROFILE_SIZE) {
- throw new OAuthException("Wrong size image at '$avatar'");
+ throw new Exception(sprintf(_('Can’t read avatar URL ‘%s’.'),
+ $avatar));
}
if (!in_array($size[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG,
IMAGETYPE_PNG))) {
- throw new OAuthException("Wrong image type for '$avatar'");
+ throw new Exception(sprintf(_('Wrong image type for avatar URL '.
+ '‘%s’.'), $avatar));
}
}
- $callback = $_GET['oauth_callback'];
- if ($callback && !common_valid_http_url($callback)) {
- throw new OAuthException("Invalid callback URL '$callback'");
- }
- if ($callback && $callback == common_local_url('finishremotesubscribe')) {
- throw new OAuthException("Callback URL '$callback' is for local site.");
- }
}
}
diff --git a/actions/userrss.php b/actions/userrss.php
index 8a940865f..a9f3fd5f8 100644
--- a/actions/userrss.php
+++ b/actions/userrss.php
@@ -88,9 +88,10 @@ class UserrssAction extends Rss10Action
$c = array('url' => common_local_url('userrss',
array('nickname' =>
$user->nickname)),
- 'title' => $user->nickname,
+ 'title' => sprintf(_('%s timeline'), $user->nickname),
'link' => $profile->profileurl,
- 'description' => sprintf(_('Microblog by %s'), $user->nickname));
+ 'description' => sprintf(_('Updates from %1$s on %2$s!'),
+ $user->nickname, common_config('site', 'name')));
return $c;
}
diff --git a/actions/xrds.php b/actions/xrds.php
index 3c7521884..b3aa8df8e 100644
--- a/actions/xrds.php
+++ b/actions/xrds.php
@@ -34,6 +34,8 @@ if (!defined('LACONICA')) {
}
require_once INSTALLDIR.'/lib/omb.php';
+require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
+require_once INSTALLDIR.'/extlib/libomb/xrds_mapper.php';
/**
* XRDS for OpenMicroBlogging
@@ -52,7 +54,7 @@ class XrdsAction extends Action
*
* @return boolean true
*/
- function isReadOnly($args)
+ function isReadOnly()
{
return true;
}
@@ -85,89 +87,31 @@ class XrdsAction extends Action
*/
function showXrds($user)
{
- header('Content-Type: application/xrds+xml');
- $this->startXML();
- $this->elementStart('XRDS', array('xmlns' => 'xri://$xrds'));
+ $srv = new OMB_Service_Provider(profile_to_omb_profile($user->uri,
+ $user->getProfile()));
+ /* Use libomb’s default XRDS Writer. */
+ $xrds_writer = null;
+ $srv->writeXRDS(new Laconica_XRDS_Mapper(), $xrds_writer);
+ }
+}
- $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');
+class Laconica_XRDS_Mapper implements OMB_XRDS_Mapper
+{
+ protected $urls;
- // 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();
+ public function __construct()
+ {
+ $this->urls = array(
+ OAUTH_ENDPOINT_REQUEST => 'requesttoken',
+ OAUTH_ENDPOINT_AUTHORIZE => 'userauthorization',
+ OAUTH_ENDPOINT_ACCESS => 'accesstoken',
+ OMB_ENDPOINT_POSTNOTICE => 'postnotice',
+ OMB_ENDPOINT_UPDATEPROFILE => 'updateprofile');
}
- /**
- * 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)
+ public function getURL($action)
{
- $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');
+ return common_local_url($this->urls[$action]);
}
}
-
+?>