summaryrefslogtreecommitdiff
path: root/actions
diff options
context:
space:
mode:
Diffstat (limited to 'actions')
-rw-r--r--actions/apitimelineuser.php5
-rw-r--r--actions/groupmembers.php4
-rw-r--r--actions/makeadmin.php3
-rw-r--r--actions/public.php10
-rw-r--r--actions/rsd.php226
-rw-r--r--actions/showstream.php13
-rw-r--r--actions/userauthorization.php21
7 files changed, 268 insertions, 14 deletions
diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php
index 830b16941..ed9104905 100644
--- a/actions/apitimelineuser.php
+++ b/actions/apitimelineuser.php
@@ -145,10 +145,11 @@ class ApiTimelineUserAction extends ApiBareAuthAction
);
break;
case 'atom':
- if (isset($apidata['api_arg'])) {
+ $id = $this->arg('id');
+ if ($id) {
$selfuri = common_root_url() .
'api/statuses/user_timeline/' .
- $apidata['api_arg'] . '.atom';
+ rawurlencode($id) . '.atom';
} else {
$selfuri = common_root_url() .
'api/statuses/user_timeline.atom';
diff --git a/actions/groupmembers.php b/actions/groupmembers.php
index 0f47c268d..f16e972a4 100644
--- a/actions/groupmembers.php
+++ b/actions/groupmembers.php
@@ -192,7 +192,9 @@ class GroupMemberListItem extends ProfileListItem
{
$user = common_current_user();
- if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group) &&
+ if (!empty($user) &&
+ $user->id != $this->profile->id &&
+ ($user->isAdmin($this->group) || $user->hasRight(Right::MAKEGROUPADMIN)) &&
!$this->profile->isAdmin($this->group)) {
$this->out->elementStart('li', 'entity_make_admin');
$maf = new MakeAdminForm($this->out, $this->profile, $this->group,
diff --git a/actions/makeadmin.php b/actions/makeadmin.php
index 9ad7d6e7c..f19348648 100644
--- a/actions/makeadmin.php
+++ b/actions/makeadmin.php
@@ -87,7 +87,8 @@ class MakeadminAction extends Action
return false;
}
$user = common_current_user();
- if (!$user->isAdmin($this->group)) {
+ if (!$user->isAdmin($this->group) &&
+ !$user->hasRight(Right::MAKEGROUPADMIN)) {
$this->clientError(_('Only an admin can make another user an admin.'), 401);
return false;
}
diff --git a/actions/public.php b/actions/public.php
index 982dfde15..50278bfce 100644
--- a/actions/public.php
+++ b/actions/public.php
@@ -131,12 +131,20 @@ class PublicAction extends Action
return _('Public timeline');
}
}
-
+
function extraHead()
{
parent::extraHead();
$this->element('meta', array('http-equiv' => 'X-XRDS-Location',
'content' => common_local_url('publicxrds')));
+
+ $rsd = common_local_url('rsd');
+
+ // RSD, http://tales.phrasewise.com/rfc/rsd
+
+ $this->element('link', array('rel' => 'EditURI',
+ 'type' => 'application/rsd+xml',
+ 'href' => $rsd));
}
/**
diff --git a/actions/rsd.php b/actions/rsd.php
new file mode 100644
index 000000000..f88bf2e9a
--- /dev/null
+++ b/actions/rsd.php
@@ -0,0 +1,226 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008-2010, StatusNet, Inc.
+ *
+ * Really Simple Discovery (RSD) for API access
+ *
+ * PHP version 5
+ *
+ * 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 API
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://status.net/
+ *
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+/**
+ * RSD action class
+ *
+ * Really Simple Discovery (RSD) is a simple (to a fault, maybe)
+ * discovery tool for blog APIs.
+ *
+ * http://tales.phrasewise.com/rfc/rsd
+ *
+ * Anil Dash suggested that RSD be used for services that implement
+ * the Twitter API:
+ *
+ * http://dashes.com/anil/2009/12/the-twitter-api-is-finished.html
+ *
+ * It's in use now for WordPress.com blogs:
+ *
+ * http://matt.wordpress.com/xmlrpc.php?rsd
+ *
+ * I (evan@status.net) have tried to stay faithful to the premise of
+ * RSD, while adding information useful to StatusNet client developers.
+ * In particular:
+ *
+ * - There is a link from each user's profile page to their personal
+ * RSD feed. A personal rsd.xml includes a 'blogID' element that is
+ * their username.
+ * - There is a link from the public root to '/rsd.xml', a public RSD
+ * feed. It's identical to the personal rsd except it doesn't include
+ * a blogId.
+ * - I've added a setting to the API to indicate that OAuth support is
+ * available.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://status.net/
+ */
+
+class RsdAction extends Action
+{
+ /**
+ * Optional attribute for the personal rsd.xml file.
+ */
+
+ var $user = null;
+
+ /**
+ * Prepare the action for use.
+ *
+ * Check for a nickname; redirect if non-canonical; if
+ * not provided, assume public rsd.xml.
+ *
+ * @param array $args GET, POST, and URI arguments.
+ *
+ * @return boolean success flag
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ // optional argument
+
+ $nickname_arg = $this->arg('nickname');
+
+ if (empty($nickname_arg)) {
+ $this->user = null;
+ } else {
+ $nickname = common_canonical_nickname($nickname_arg);
+
+ // Permanent redirect on non-canonical nickname
+
+ if ($nickname_arg != $nickname) {
+ common_redirect(common_local_url('rsd',
+ array('nickname' => $nickname)),
+ 301);
+ return false;
+ }
+
+ $this->user = User::staticGet('nickname', $nickname);
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user.'), 404);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Action handler.
+ *
+ * Outputs the XML format for an RSD file. May include
+ * personal information if this is a personal file
+ * (based on whether $user attribute is set).
+ *
+ * @param array $args array of arguments
+ *
+ * @return nothing
+ */
+
+ function handle($args)
+ {
+ header('Content-Type: application/rsd+xml');
+
+ $this->startXML();
+
+ $rsdNS = 'http://archipelago.phrasewise.com/rsd';
+ $this->elementStart('rsd', array('version' => '1.0',
+ 'xmlns' => $rsdNS));
+ $this->elementStart('service');
+ $this->element('engineName', null, _('StatusNet'));
+ $this->element('engineLink', null, 'http://status.net/');
+ $this->elementStart('apis');
+ if (Event::handle('StartRsdListApis', array($this, $this->user))) {
+
+ $blogID = (empty($this->user)) ? '' : $this->user->nickname;
+ $apiAttrs = array('name' => 'Twitter',
+ 'preferred' => 'true',
+ 'apiLink' => $this->_apiRoot(),
+ 'blogID' => $blogID);
+
+ $this->elementStart('api', $apiAttrs);
+ $this->elementStart('settings');
+ $this->element('docs', null,
+ 'http://status.net/wiki/TwitterCompatibleAPI');
+ $this->element('setting', array('name' => 'OAuth'),
+ 'true');
+ $this->elementEnd('settings');
+ $this->elementEnd('api');
+ Event::handle('EndRsdListApis', array($this, $this->user));
+ }
+ $this->elementEnd('apis');
+ $this->elementEnd('service');
+ $this->elementEnd('rsd');
+
+ $this->endXML();
+
+ return true;
+ }
+
+ /**
+ * Returns last-modified date for use in caching
+ *
+ * Per-user rsd.xml is dated to last change of user
+ * (in case of nickname change); public has no date.
+ *
+ * @return string date of last change of this page
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->user)) {
+ return $this->user->modified;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Flag to indicate if this action is read-only
+ *
+ * It is; it doesn't change the DB.
+ *
+ * @param array $args ignored
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * Return current site's API root
+ *
+ * Varies based on URL parameters, like if fancy URLs are
+ * turned on.
+ *
+ * @return string API root URI for this site
+ */
+
+ private function _apiRoot()
+ {
+ if (common_config('site', 'fancy')) {
+ return common_path('api/', true);
+ } else {
+ return common_path('index.php/api/', true);
+ }
+ }
+}
diff --git a/actions/showstream.php b/actions/showstream.php
index c52919386..f9407e35a 100644
--- a/actions/showstream.php
+++ b/actions/showstream.php
@@ -131,14 +131,14 @@ class ShowstreamAction extends ProfileAction
new Feed(Feed::RSS2,
common_local_url('ApiTimelineUser',
array(
- 'id' => $this->user->nickname,
+ 'id' => $this->user->id,
'format' => 'rss')),
sprintf(_('Notice feed for %s (RSS 2.0)'),
$this->user->nickname)),
new Feed(Feed::ATOM,
common_local_url('ApiTimelineUser',
array(
- 'id' => $this->user->nickname,
+ 'id' => $this->user->id,
'format' => 'atom')),
sprintf(_('Notice feed for %s (Atom)'),
$this->user->nickname)),
@@ -178,6 +178,15 @@ class ShowstreamAction extends ProfileAction
$this->element('link', array('rel' => 'microsummary',
'href' => common_local_url('microsummary',
array('nickname' => $this->profile->nickname))));
+
+ $rsd = common_local_url('rsd',
+ array('nickname' => $this->profile->nickname));
+
+ // RSD, http://tales.phrasewise.com/rfc/rsd
+ $this->element('link', array('rel' => 'EditURI',
+ 'type' => 'application/rsd+xml',
+ 'href' => $rsd));
+
}
function showProfile()
diff --git a/actions/userauthorization.php b/actions/userauthorization.php
index 4321f1302..7f71c60db 100644
--- a/actions/userauthorization.php
+++ b/actions/userauthorization.php
@@ -127,10 +127,10 @@ class UserauthorizationAction extends Action
$location = $params->getLocation();
$avatar = $params->getAvatarURL();
- $this->elementStart('div', array('class' => 'profile'));
$this->elementStart('div', 'entity_profile vcard');
- $this->elementStart('a', array('href' => $profile,
- 'class' => 'url'));
+ $this->elementStart('dl', 'entity_depiction');
+ $this->element('dt', null, _('Photo'));
+ $this->elementStart('dd');
if ($avatar) {
$this->element('img', array('src' => $avatar,
'class' => 'photo avatar',
@@ -138,11 +138,19 @@ class UserauthorizationAction extends Action
'height' => AVATAR_PROFILE_SIZE,
'alt' => $nickname));
}
+ $this->elementEnd('dd');
+ $this->elementEnd('dl');
+
+ $this->elementStart('dl', 'entity_nickname');
+ $this->element('dt', null, _('Nickname'));
+ $this->elementStart('dd');
$hasFN = ($fullname !== '') ? 'nickname' : 'fn nickname';
- $this->elementStart('span', $hasFN);
+ $this->elementStart('a', array('href' => $profile,
+ 'class' => 'url '.$hasFN));
$this->raw($nickname);
- $this->elementEnd('span');
$this->elementEnd('a');
+ $this->elementEnd('dd');
+ $this->elementEnd('dl');
if (!is_null($fullname)) {
$this->elementStart('dl', 'entity_fn');
@@ -214,7 +222,6 @@ class UserauthorizationAction extends Action
$this->elementEnd('li');
$this->elementEnd('ul');
$this->elementEnd('div');
- $this->elementEnd('div');
}
function sendAuthorization()
@@ -350,4 +357,4 @@ class UserauthorizationAction extends Action
}
}
}
-} \ No newline at end of file
+}