Merge branch 'testing'
This commit is contained in:
commit
62d5f1addb
|
@ -83,6 +83,7 @@ class AllrssAction extends Rss10Action
|
|||
function getNotices($limit=0)
|
||||
{
|
||||
$cur = common_current_user();
|
||||
$user = $this->user;
|
||||
|
||||
if (!empty($cur) && $cur->id == $user->id) {
|
||||
$notice = $this->user->noticeInbox(0, $limit);
|
||||
|
@ -90,7 +91,6 @@ class AllrssAction extends Rss10Action
|
|||
$notice = $this->user->noticesWithFriends(0, $limit);
|
||||
}
|
||||
|
||||
$user = $this->user;
|
||||
$notice = $user->noticesWithFriends(0, $limit);
|
||||
$notices = array();
|
||||
|
||||
|
|
|
@ -104,30 +104,21 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction
|
|||
|
||||
function showTimeline()
|
||||
{
|
||||
$sitename = common_config('site', 'name');
|
||||
$avatar = $this->group->homepage_logo;
|
||||
$title = sprintf(_("%s timeline"), $this->group->nickname);
|
||||
|
||||
$subtitle = sprintf(
|
||||
_('Updates from %1$s on %2$s!'),
|
||||
$this->group->nickname,
|
||||
$sitename
|
||||
);
|
||||
|
||||
$logo = ($avatar) ? $avatar : User_group::defaultLogo(AVATAR_PROFILE_SIZE);
|
||||
// We'll pull common formatting out of this for other formats
|
||||
$atom = new AtomGroupNoticeFeed($this->group);
|
||||
|
||||
switch($this->format) {
|
||||
case 'xml':
|
||||
$this->showXmlTimeline($this->notices);
|
||||
break;
|
||||
case 'rss':
|
||||
$this->showRssTimeline(
|
||||
$this->showRssTimeline(
|
||||
$this->notices,
|
||||
$title,
|
||||
$atom->title,
|
||||
$this->group->homeUrl(),
|
||||
$subtitle,
|
||||
$atom->subtitle,
|
||||
null,
|
||||
$logo
|
||||
$atom->logo
|
||||
);
|
||||
break;
|
||||
case 'atom':
|
||||
|
@ -136,38 +127,22 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction
|
|||
|
||||
try {
|
||||
|
||||
$atom = new AtomGroupNoticeFeed($this->group);
|
||||
|
||||
// @todo set all this Atom junk up inside the feed class
|
||||
|
||||
#$atom->setId($id);
|
||||
$atom->setTitle($title);
|
||||
$atom->setSubtitle($subtitle);
|
||||
$atom->setLogo($logo);
|
||||
$atom->setUpdated('now');
|
||||
|
||||
$atom->addAuthorRaw($this->group->asAtomAuthor());
|
||||
$atom->setActivitySubject($this->group->asActivitySubject());
|
||||
|
||||
$atom->addLink($this->group->homeUrl());
|
||||
|
||||
$id = $this->arg('id');
|
||||
$aargs = array('format' => 'atom');
|
||||
if (!empty($id)) {
|
||||
$aargs['id'] = $id;
|
||||
}
|
||||
$self = $this->getSelfUri('ApiTimelineGroup', $aargs);
|
||||
|
||||
$atom->setId($this->getSelfUri('ApiTimelineGroup', $aargs));
|
||||
|
||||
$atom->addLink(
|
||||
$this->getSelfUri('ApiTimelineGroup', $aargs),
|
||||
array('rel' => 'self', 'type' => 'application/atom+xml')
|
||||
);
|
||||
$atom->setId($self);
|
||||
$atom->setSelfLink($self);
|
||||
|
||||
$atom->addEntryFromNotices($this->notices);
|
||||
|
||||
//$this->raw($atom->getString());
|
||||
print $atom->getString(); // temp hack until PuSH feeds are redone cleanly
|
||||
$this->raw($atom->getString());
|
||||
|
||||
} catch (Atom10FeedException $e) {
|
||||
$this->serverError(
|
||||
|
|
|
@ -112,19 +112,17 @@ class ApiTimelineUserAction extends ApiBareAuthAction
|
|||
function showTimeline()
|
||||
{
|
||||
$profile = $this->user->getProfile();
|
||||
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
$title = sprintf(_("%s timeline"), $this->user->nickname);
|
||||
// We'll use the shared params from the Atom stub
|
||||
// for other feed types.
|
||||
$atom = new AtomUserNoticeFeed($this->user);
|
||||
$title = $atom->title;
|
||||
$link = common_local_url(
|
||||
'showstream',
|
||||
array('nickname' => $this->user->nickname)
|
||||
);
|
||||
$subtitle = sprintf(
|
||||
_('Updates from %1$s on %2$s!'),
|
||||
$this->user->nickname, $sitename
|
||||
);
|
||||
$logo = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE);
|
||||
$subtitle = $atom->subtitle;
|
||||
$logo = $atom->logo;
|
||||
|
||||
// FriendFeed's SUP protocol
|
||||
// Also added RSS and Atom feeds
|
||||
|
@ -146,47 +144,18 @@ class ApiTimelineUserAction extends ApiBareAuthAction
|
|||
|
||||
header('Content-Type: application/atom+xml; charset=utf-8');
|
||||
|
||||
// @todo set all this Atom junk up inside the feed class
|
||||
|
||||
$atom = new AtomUserNoticeFeed($this->user);
|
||||
|
||||
$atom->setTitle($title);
|
||||
$atom->setSubtitle($subtitle);
|
||||
$atom->setLogo($logo);
|
||||
$atom->setUpdated('now');
|
||||
|
||||
$atom->addLink(
|
||||
common_local_url(
|
||||
'showstream',
|
||||
array('nickname' => $this->user->nickname)
|
||||
)
|
||||
);
|
||||
|
||||
$id = $this->arg('id');
|
||||
$aargs = array('format' => 'atom');
|
||||
if (!empty($id)) {
|
||||
$aargs['id'] = $id;
|
||||
}
|
||||
|
||||
$atom->setId($this->getSelfUri('ApiTimelineUser', $aargs));
|
||||
|
||||
$atom->addLink(
|
||||
$this->getSelfUri('ApiTimelineUser', $aargs),
|
||||
array('rel' => 'self', 'type' => 'application/atom+xml')
|
||||
);
|
||||
|
||||
$atom->addLink(
|
||||
$suplink,
|
||||
array(
|
||||
'rel' => 'http://api.friendfeed.com/2008/03#sup',
|
||||
'type' => 'application/json'
|
||||
)
|
||||
);
|
||||
$self = $this->getSelfUri('ApiTimelineUser', $aargs);
|
||||
$atom->setId($self);
|
||||
$atom->setSelfLink($self);
|
||||
|
||||
$atom->addEntryFromNotices($this->notices);
|
||||
|
||||
#$this->raw($atom->getString());
|
||||
print $atom->getString(); // temporary for output buffering
|
||||
$this->raw($atom->getString());
|
||||
|
||||
break;
|
||||
case 'json':
|
||||
|
|
99
actions/grantrole.php
Normal file
99
actions/grantrole.php
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Action class to sandbox an abusive user
|
||||
*
|
||||
* 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 Action
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sandbox a user.
|
||||
*
|
||||
* @category Action
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
class GrantRoleAction extends ProfileFormAction
|
||||
{
|
||||
/**
|
||||
* Check parameters
|
||||
*
|
||||
* @param array $args action arguments (URL, GET, POST)
|
||||
*
|
||||
* @return boolean success flag
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
if (!parent::prepare($args)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->role = $this->arg('role');
|
||||
if (!Profile_role::isValid($this->role)) {
|
||||
$this->clientError(_("Invalid role."));
|
||||
return false;
|
||||
}
|
||||
if (!Profile_role::isSettable($this->role)) {
|
||||
$this->clientError(_("This role is reserved and cannot be set."));
|
||||
return false;
|
||||
}
|
||||
|
||||
$cur = common_current_user();
|
||||
|
||||
assert(!empty($cur)); // checked by parent
|
||||
|
||||
if (!$cur->hasRight(Right::GRANTROLE)) {
|
||||
$this->clientError(_("You cannot grant user roles on this site."));
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(!empty($this->profile)); // checked by parent
|
||||
|
||||
if ($this->profile->hasRole($this->role)) {
|
||||
$this->clientError(_("User already has this role."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sandbox a user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handlePost()
|
||||
{
|
||||
$this->profile->grantRole($this->role);
|
||||
}
|
||||
}
|
99
actions/revokerole.php
Normal file
99
actions/revokerole.php
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Action class to sandbox an abusive user
|
||||
*
|
||||
* 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 Action
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @copyright 2009 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sandbox a user.
|
||||
*
|
||||
* @category Action
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
class RevokeRoleAction extends ProfileFormAction
|
||||
{
|
||||
/**
|
||||
* Check parameters
|
||||
*
|
||||
* @param array $args action arguments (URL, GET, POST)
|
||||
*
|
||||
* @return boolean success flag
|
||||
*/
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
if (!parent::prepare($args)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->role = $this->arg('role');
|
||||
if (!Profile_role::isValid($this->role)) {
|
||||
$this->clientError(_("Invalid role."));
|
||||
return false;
|
||||
}
|
||||
if (!Profile_role::isSettable($this->role)) {
|
||||
$this->clientError(_("This role is reserved and cannot be set."));
|
||||
return false;
|
||||
}
|
||||
|
||||
$cur = common_current_user();
|
||||
|
||||
assert(!empty($cur)); // checked by parent
|
||||
|
||||
if (!$cur->hasRight(Right::REVOKEROLE)) {
|
||||
$this->clientError(_("You cannot revoke user roles on this site."));
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(!empty($this->profile)); // checked by parent
|
||||
|
||||
if (!$this->profile->hasRole($this->role)) {
|
||||
$this->clientError(_("User doesn't have this role."));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sandbox a user.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function handlePost()
|
||||
{
|
||||
$this->profile->revokeRole($this->role);
|
||||
}
|
||||
}
|
|
@ -66,7 +66,7 @@ class SiteadminpanelAction extends AdminPanelAction
|
|||
|
||||
function getInstructions()
|
||||
{
|
||||
return _('Basic settings for this StatusNet site.');
|
||||
return _('Basic settings for this StatusNet site');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,10 +90,11 @@ class SiteadminpanelAction extends AdminPanelAction
|
|||
|
||||
function saveSettings()
|
||||
{
|
||||
static $settings = array('site' => array('name', 'broughtby', 'broughtbyurl',
|
||||
'email', 'timezone', 'language',
|
||||
'site', 'textlimit', 'dupelimit'),
|
||||
'snapshot' => array('run', 'reporturl', 'frequency'));
|
||||
static $settings = array(
|
||||
'site' => array('name', 'broughtby', 'broughtbyurl',
|
||||
'email', 'timezone', 'language',
|
||||
'site', 'textlimit', 'dupelimit'),
|
||||
);
|
||||
|
||||
$values = array();
|
||||
|
||||
|
@ -158,25 +159,6 @@ class SiteadminpanelAction extends AdminPanelAction
|
|||
$this->clientError(sprintf(_('Unknown language "%s".'), $values['site']['language']));
|
||||
}
|
||||
|
||||
// Validate report URL
|
||||
|
||||
if (!is_null($values['snapshot']['reporturl']) &&
|
||||
!Validate::uri($values['snapshot']['reporturl'], array('allowed_schemes' => array('http', 'https')))) {
|
||||
$this->clientError(_("Invalid snapshot report URL."));
|
||||
}
|
||||
|
||||
// Validate snapshot run value
|
||||
|
||||
if (!in_array($values['snapshot']['run'], array('web', 'cron', 'never'))) {
|
||||
$this->clientError(_("Invalid snapshot run value."));
|
||||
}
|
||||
|
||||
// Validate snapshot run value
|
||||
|
||||
if (!Validate::number($values['snapshot']['frequency'])) {
|
||||
$this->clientError(_("Snapshot frequency must be a number."));
|
||||
}
|
||||
|
||||
// Validate text limit
|
||||
|
||||
if (!Validate::number($values['site']['textlimit'], array('min' => 140))) {
|
||||
|
@ -285,32 +267,6 @@ class SiteAdminPanelForm extends AdminForm
|
|||
$this->out->elementEnd('ul');
|
||||
$this->out->elementEnd('fieldset');
|
||||
|
||||
$this->out->elementStart('fieldset', array('id' => 'settings_admin_snapshots'));
|
||||
$this->out->element('legend', null, _('Snapshots'));
|
||||
$this->out->elementStart('ul', 'form_data');
|
||||
$this->li();
|
||||
$snapshot = array('web' => _('Randomly during Web hit'),
|
||||
'cron' => _('In a scheduled job'),
|
||||
'never' => _('Never'));
|
||||
$this->out->dropdown('run', _('Data snapshots'),
|
||||
$snapshot, _('When to send statistical data to status.net servers'),
|
||||
false, $this->value('run', 'snapshot'));
|
||||
$this->unli();
|
||||
|
||||
$this->li();
|
||||
$this->input('frequency', _('Frequency'),
|
||||
_('Snapshots will be sent once every N web hits'),
|
||||
'snapshot');
|
||||
$this->unli();
|
||||
|
||||
$this->li();
|
||||
$this->input('reporturl', _('Report URL'),
|
||||
_('Snapshots will be sent to this URL'),
|
||||
'snapshot');
|
||||
$this->unli();
|
||||
$this->out->elementEnd('ul');
|
||||
$this->out->elementEnd('fieldset');
|
||||
|
||||
$this->out->elementStart('fieldset', array('id' => 'settings_admin_limits'));
|
||||
$this->out->element('legend', null, _('Limits'));
|
||||
$this->out->elementStart('ul', 'form_data');
|
||||
|
|
|
@ -99,7 +99,7 @@ class SitenoticeadminpanelAction extends AdminPanelAction
|
|||
|
||||
$result = Config::save('site', 'notice', $siteNotice);
|
||||
|
||||
if (!result) {
|
||||
if (!$result) {
|
||||
$this->ServerError(_("Unable to save site notice."));
|
||||
}
|
||||
}
|
||||
|
|
251
actions/snapshotadminpanel.php
Normal file
251
actions/snapshotadminpanel.php
Normal file
|
@ -0,0 +1,251 @@
|
|||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Snapshots administration panel
|
||||
*
|
||||
* 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 Settings
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage snapshots
|
||||
*
|
||||
* @category Admin
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
class SnapshotadminpanelAction extends AdminPanelAction
|
||||
{
|
||||
/**
|
||||
* Returns the page title
|
||||
*
|
||||
* @return string page title
|
||||
*/
|
||||
|
||||
function title()
|
||||
{
|
||||
return _('Snapshots');
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructions for using this form.
|
||||
*
|
||||
* @return string instructions
|
||||
*/
|
||||
|
||||
function getInstructions()
|
||||
{
|
||||
return _('Manage snapshot configuration');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the snapshots admin panel form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function showForm()
|
||||
{
|
||||
$form = new SnapshotAdminPanelForm($this);
|
||||
$form->show();
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save settings from the form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function saveSettings()
|
||||
{
|
||||
static $settings = array(
|
||||
'snapshot' => array('run', 'reporturl', 'frequency')
|
||||
);
|
||||
|
||||
$values = array();
|
||||
|
||||
foreach ($settings as $section => $parts) {
|
||||
foreach ($parts as $setting) {
|
||||
$values[$section][$setting] = $this->trimmed($setting);
|
||||
}
|
||||
}
|
||||
|
||||
// This throws an exception on validation errors
|
||||
|
||||
$this->validate($values);
|
||||
|
||||
// assert(all values are valid);
|
||||
|
||||
$config = new Config();
|
||||
|
||||
$config->query('BEGIN');
|
||||
|
||||
foreach ($settings as $section => $parts) {
|
||||
foreach ($parts as $setting) {
|
||||
Config::save($section, $setting, $values[$section][$setting]);
|
||||
}
|
||||
}
|
||||
|
||||
$config->query('COMMIT');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
function validate(&$values)
|
||||
{
|
||||
// Validate snapshot run value
|
||||
|
||||
if (!in_array($values['snapshot']['run'], array('web', 'cron', 'never'))) {
|
||||
$this->clientError(_("Invalid snapshot run value."));
|
||||
}
|
||||
|
||||
// Validate snapshot frequency value
|
||||
|
||||
if (!Validate::number($values['snapshot']['frequency'])) {
|
||||
$this->clientError(_("Snapshot frequency must be a number."));
|
||||
}
|
||||
|
||||
// Validate report URL
|
||||
|
||||
if (!is_null($values['snapshot']['reporturl'])
|
||||
&& !Validate::uri(
|
||||
$values['snapshot']['reporturl'],
|
||||
array('allowed_schemes' => array('http', 'https')
|
||||
)
|
||||
)) {
|
||||
$this->clientError(_("Invalid snapshot report URL."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SnapshotAdminPanelForm extends AdminForm
|
||||
{
|
||||
/**
|
||||
* ID of the form
|
||||
*
|
||||
* @return int ID of the form
|
||||
*/
|
||||
|
||||
function id()
|
||||
{
|
||||
return 'form_snapshot_admin_panel';
|
||||
}
|
||||
|
||||
/**
|
||||
* class of the form
|
||||
*
|
||||
* @return string class of the form
|
||||
*/
|
||||
|
||||
function formClass()
|
||||
{
|
||||
return 'form_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Action of the form
|
||||
*
|
||||
* @return string URL of the action
|
||||
*/
|
||||
|
||||
function action()
|
||||
{
|
||||
return common_local_url('snapshotadminpanel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Data elements of the form
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function formData()
|
||||
{
|
||||
$this->out->elementStart(
|
||||
'fieldset',
|
||||
array('id' => 'settings_admin_snapshots')
|
||||
);
|
||||
$this->out->element('legend', null, _('Snapshots'));
|
||||
$this->out->elementStart('ul', 'form_data');
|
||||
$this->li();
|
||||
$snapshot = array(
|
||||
'web' => _('Randomly during Web hit'),
|
||||
'cron' => _('In a scheduled job'),
|
||||
'never' => _('Never')
|
||||
);
|
||||
$this->out->dropdown(
|
||||
'run',
|
||||
_('Data snapshots'),
|
||||
$snapshot,
|
||||
_('When to send statistical data to status.net servers'),
|
||||
false,
|
||||
$this->value('run', 'snapshot')
|
||||
);
|
||||
$this->unli();
|
||||
|
||||
$this->li();
|
||||
$this->input(
|
||||
'frequency',
|
||||
_('Frequency'),
|
||||
_('Snapshots will be sent once every N web hits'),
|
||||
'snapshot'
|
||||
);
|
||||
$this->unli();
|
||||
|
||||
$this->li();
|
||||
$this->input(
|
||||
'reporturl',
|
||||
_('Report URL'),
|
||||
_('Snapshots will be sent to this URL'),
|
||||
'snapshot'
|
||||
);
|
||||
$this->unli();
|
||||
$this->out->elementEnd('ul');
|
||||
$this->out->elementEnd('fieldset');
|
||||
}
|
||||
|
||||
/**
|
||||
* Action elements
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function formActions()
|
||||
{
|
||||
$this->out->submit(
|
||||
'submit',
|
||||
_('Save'),
|
||||
'submit',
|
||||
null,
|
||||
_('Save snapshot settings')
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1106,7 +1106,7 @@ class Notice extends Memcached_DataObject
|
|||
return $groups;
|
||||
}
|
||||
|
||||
function asAtomEntry($namespace=false, $source=false)
|
||||
function asAtomEntry($namespace=false, $source=false, $author=true)
|
||||
{
|
||||
$profile = $this->getProfile();
|
||||
|
||||
|
@ -1151,8 +1151,10 @@ class Notice extends Memcached_DataObject
|
|||
|
||||
$xs->element('title', null, $this->content);
|
||||
|
||||
$xs->raw($profile->asAtomAuthor());
|
||||
$xs->raw($profile->asActivityActor());
|
||||
if ($author) {
|
||||
$xs->raw($profile->asAtomAuthor());
|
||||
$xs->raw($profile->asActivityActor());
|
||||
}
|
||||
|
||||
$xs->element('link', array('rel' => 'alternate',
|
||||
'type' => 'text/html',
|
||||
|
|
|
@ -743,6 +743,10 @@ class Profile extends Memcached_DataObject
|
|||
case Right::CONFIGURESITE:
|
||||
$result = $this->hasRole(Profile_role::ADMINISTRATOR);
|
||||
break;
|
||||
case Right::GRANTROLE:
|
||||
case Right::REVOKEROLE:
|
||||
$result = $this->hasRole(Profile_role::OWNER);
|
||||
break;
|
||||
case Right::NEWNOTICE:
|
||||
case Right::NEWMESSAGE:
|
||||
case Right::SUBSCRIBE:
|
||||
|
|
|
@ -53,4 +53,21 @@ class Profile_role extends Memcached_DataObject
|
|||
const ADMINISTRATOR = 'administrator';
|
||||
const SANDBOXED = 'sandboxed';
|
||||
const SILENCED = 'silenced';
|
||||
|
||||
public static function isValid($role)
|
||||
{
|
||||
// @fixme could probably pull this from class constants
|
||||
$known = array(self::OWNER,
|
||||
self::MODERATOR,
|
||||
self::ADMINISTRATOR,
|
||||
self::SANDBOXED,
|
||||
self::SILENCED);
|
||||
return in_array($role, $known);
|
||||
}
|
||||
|
||||
public static function isSettable($role)
|
||||
{
|
||||
$allowedRoles = array('administrator', 'moderator');
|
||||
return self::isValid($role) && in_array($role, $allowedRoles);
|
||||
}
|
||||
}
|
||||
|
|
86
install.php
86
install.php
|
@ -31,6 +31,7 @@
|
|||
* @author Robin Millette <millette@controlyourself.ca>
|
||||
* @author Sarven Capadisli <csarven@status.net>
|
||||
* @author Tom Adams <tom@holizz.com>
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @license GNU Affero General Public License http://www.gnu.org/licenses/
|
||||
* @version 0.9.x
|
||||
* @link http://status.net
|
||||
|
@ -490,15 +491,25 @@ function showForm()
|
|||
<p class="form_guide">Database name</p>
|
||||
</li>
|
||||
<li>
|
||||
<label for="username">Username</label>
|
||||
<label for="username">DB username</label>
|
||||
<input type="text" id="username" name="username" />
|
||||
<p class="form_guide">Database username</p>
|
||||
</li>
|
||||
<li>
|
||||
<label for="password">Password</label>
|
||||
<label for="password">DB password</label>
|
||||
<input type="password" id="password" name="password" />
|
||||
<p class="form_guide">Database password (optional)</p>
|
||||
</li>
|
||||
<li>
|
||||
<label for="admin_nickname">Administrator nickname</label>
|
||||
<input type="text" id="admin_nickname" name="admin_nickname" />
|
||||
<p class="form_guide">Nickname for the initial StatusNet user (administrator)</p>
|
||||
</li>
|
||||
<li>
|
||||
<label for="initial_user_password">Administrator password</label>
|
||||
<input type="password" id="admin_password" name="admin_password" />
|
||||
<p class="form_guide">Password for the initial StatusNet user (administrator)</p>
|
||||
</li>
|
||||
</ul>
|
||||
<input type="submit" name="submit" class="submit" value="Submit" />
|
||||
</fieldset>
|
||||
|
@ -521,6 +532,10 @@ function handlePost()
|
|||
$password = $_POST['password'];
|
||||
$sitename = $_POST['sitename'];
|
||||
$fancy = !empty($_POST['fancy']);
|
||||
|
||||
$adminNick = $_POST['admin_nickname'];
|
||||
$adminPass = $_POST['admin_password'];
|
||||
|
||||
$server = $_SERVER['HTTP_HOST'];
|
||||
$path = substr(dirname($_SERVER['PHP_SELF']), 1);
|
||||
|
||||
|
@ -552,6 +567,16 @@ STR;
|
|||
$fail = true;
|
||||
}
|
||||
|
||||
if (empty($adminNick)) {
|
||||
updateStatus("No initial StatusNet user nickname specified.", true);
|
||||
$fail = true;
|
||||
}
|
||||
|
||||
if (empty($adminPass)) {
|
||||
updateStatus("No initial StatusNet user password specified.", true);
|
||||
$fail = true;
|
||||
}
|
||||
|
||||
if ($fail) {
|
||||
showForm();
|
||||
return;
|
||||
|
@ -574,13 +599,29 @@ STR;
|
|||
return;
|
||||
}
|
||||
|
||||
// Okay, cross fingers and try to register an initial user
|
||||
if (registerInitialUser($adminNick, $adminPass)) {
|
||||
updateStatus(
|
||||
"An initial user with the administrator role has been created."
|
||||
);
|
||||
} else {
|
||||
updateStatus(
|
||||
"Could not create initial StatusNet user (administrator).",
|
||||
true
|
||||
);
|
||||
showForm();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
TODO https needs to be considered
|
||||
*/
|
||||
$link = "http://".$server.'/'.$path;
|
||||
|
||||
updateStatus("StatusNet has been installed at $link");
|
||||
updateStatus("You can visit your <a href='$link'>new StatusNet site</a>.");
|
||||
updateStatus(
|
||||
"You can visit your <a href='$link'>new StatusNet site</a> (login as '$adminNick')."
|
||||
);
|
||||
}
|
||||
|
||||
function Pgsql_Db_installer($host, $database, $username, $password)
|
||||
|
@ -756,6 +797,33 @@ function runDbScript($filename, $conn, $type = 'mysqli')
|
|||
return true;
|
||||
}
|
||||
|
||||
function registerInitialUser($nickname, $password)
|
||||
{
|
||||
define('STATUSNET', true);
|
||||
define('LACONICA', true); // compatibility
|
||||
|
||||
require_once INSTALLDIR . '/lib/common.php';
|
||||
|
||||
$user = User::register(
|
||||
array('nickname' => $nickname,
|
||||
'password' => $password,
|
||||
'fullname' => $nickname
|
||||
)
|
||||
);
|
||||
|
||||
if (empty($user)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// give initial user carte blanche
|
||||
|
||||
$user->grantRole('owner');
|
||||
$user->grantRole('moderator');
|
||||
$user->grantRole('administrator');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
?>
|
||||
<?php echo"<?"; ?> xml version="1.0" encoding="UTF-8" <?php echo "?>"; ?>
|
||||
<!DOCTYPE html
|
||||
|
@ -765,10 +833,10 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
|||
<head>
|
||||
<title>Install StatusNet</title>
|
||||
<link rel="shortcut icon" href="favicon.ico"/>
|
||||
<link rel="stylesheet" type="text/css" href="theme/default/css/display.css?version=0.8" media="screen, projection, tv"/>
|
||||
<!--[if IE]><link rel="stylesheet" type="text/css" href="theme/base/css/ie.css?version=0.8" /><![endif]-->
|
||||
<!--[if lte IE 6]><link rel="stylesheet" type="text/css" theme/base/css/ie6.css?version=0.8" /><![endif]-->
|
||||
<!--[if IE]><link rel="stylesheet" type="text/css" href="theme/default/css/ie.css?version=0.8" /><![endif]-->
|
||||
<link rel="stylesheet" type="text/css" href="theme/default/css/display.css" media="screen, projection, tv"/>
|
||||
<!--[if IE]><link rel="stylesheet" type="text/css" href="theme/base/css/ie.css" /><![endif]-->
|
||||
<!--[if lte IE 6]><link rel="stylesheet" type="text/css" theme/base/css/ie6.css" /><![endif]-->
|
||||
<!--[if IE]><link rel="stylesheet" type="text/css" href="theme/default/css/ie.css" /><![endif]-->
|
||||
<script src="js/jquery.min.js"></script>
|
||||
<script src="js/install.js"></script>
|
||||
</head>
|
||||
|
@ -784,8 +852,10 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
|||
</div>
|
||||
<div id="core">
|
||||
<div id="content">
|
||||
<h1>Install StatusNet</h1>
|
||||
<div id="content_inner">
|
||||
<h1>Install StatusNet</h1>
|
||||
<?php main(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1064,6 +1064,18 @@ class Activity
|
|||
}
|
||||
|
||||
$this->entry = $entry;
|
||||
|
||||
// @fixme Don't send in a DOMDocument
|
||||
if ($feed instanceof DOMDocument) {
|
||||
common_log(
|
||||
LOG_WARNING,
|
||||
'Activity::__construct() - '
|
||||
. 'DOMDocument passed in for feed by mistake. '
|
||||
. "Expecting a 'feed' DOMElement."
|
||||
);
|
||||
$feed = $feed->getElementsByTagName('feed')->item(0);
|
||||
}
|
||||
|
||||
$this->feed = $feed;
|
||||
|
||||
$pubEl = $this->_child($entry, self::PUBLISHED, self::ATOM);
|
||||
|
|
|
@ -381,6 +381,11 @@ class AdminPanelNav extends Widget
|
|||
_('Edit site notice'), $action_name == 'sitenoticeadminpanel', 'nav_sitenotice_admin_panel');
|
||||
}
|
||||
|
||||
if (AdminPanelAction::canAdmin('snapshot')) {
|
||||
$this->out->menuItem(common_local_url('snapshotadminpanel'), _('Snapshots'),
|
||||
_('Snapshots configuration'), $action_name == 'snapshotadminpanel', 'nav_snapshot_admin_panel');
|
||||
}
|
||||
|
||||
Event::handle('EndAdminPanelNav', array($this));
|
||||
}
|
||||
$this->action->elementEnd('ul');
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Class for building / manipulating an Atom entry in memory
|
||||
*
|
||||
* 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 Feed
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @copyright 2010 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
class Atom10EntryException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for manipulating an Atom entry in memory. Get the entry as an XML
|
||||
* string with Atom10Entry::getString().
|
||||
*
|
||||
* @category Feed
|
||||
* @package StatusNet
|
||||
* @author Zach Copley <zach@status.net>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
class Atom10Entry extends XMLStringer
|
||||
{
|
||||
private $namespaces;
|
||||
private $categories;
|
||||
private $content;
|
||||
private $contributors;
|
||||
private $id;
|
||||
private $links;
|
||||
private $published;
|
||||
private $rights;
|
||||
private $source;
|
||||
private $summary;
|
||||
private $title;
|
||||
|
||||
function __construct($indent = true) {
|
||||
parent::__construct($indent);
|
||||
$this->namespaces = array();
|
||||
}
|
||||
|
||||
function addNamespace($namespace, $uri)
|
||||
{
|
||||
$ns = array($namespace => $uri);
|
||||
$this->namespaces = array_merge($this->namespaces, $ns);
|
||||
}
|
||||
|
||||
function initEntry()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
function endEntry()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that all required elements have been set, etc.
|
||||
* Throws an Atom10EntryException if something's missing.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function validate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
function getString()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
$this->initEntry();
|
||||
$this->renderEntries();
|
||||
$this->endEntry();
|
||||
|
||||
return $this->xw->outputMemory();
|
||||
}
|
||||
|
||||
}
|
|
@ -49,6 +49,8 @@ class Atom10FeedException extends Exception
|
|||
class Atom10Feed extends XMLStringer
|
||||
{
|
||||
public $xw;
|
||||
|
||||
// @fixme most of these should probably be read-only properties
|
||||
private $namespaces;
|
||||
private $authors;
|
||||
private $subject;
|
||||
|
@ -57,10 +59,12 @@ class Atom10Feed extends XMLStringer
|
|||
private $generator;
|
||||
private $icon;
|
||||
private $links;
|
||||
private $logo;
|
||||
private $selfLink;
|
||||
private $selfLinkType;
|
||||
public $logo;
|
||||
private $rights;
|
||||
private $subtitle;
|
||||
private $title;
|
||||
public $subtitle;
|
||||
public $title;
|
||||
private $published;
|
||||
private $updated;
|
||||
private $entries;
|
||||
|
@ -172,6 +176,14 @@ class Atom10Feed extends XMLStringer
|
|||
}
|
||||
$this->elementStart('feed', $commonAttrs);
|
||||
|
||||
$this->element(
|
||||
'generator', array(
|
||||
'url' => 'http://status.net',
|
||||
'version' => STATUSNET_VERSION
|
||||
),
|
||||
'StatusNet'
|
||||
);
|
||||
|
||||
$this->element('id', null, $this->id);
|
||||
$this->element('title', null, $this->title);
|
||||
$this->element('subtitle', null, $this->subtitle);
|
||||
|
@ -184,6 +196,10 @@ class Atom10Feed extends XMLStringer
|
|||
|
||||
$this->renderAuthors();
|
||||
|
||||
if ($this->selfLink) {
|
||||
$this->addLink($this->selfLink, array('rel' => 'self',
|
||||
'type' => $this->selfLinkType));
|
||||
}
|
||||
$this->renderLinks();
|
||||
}
|
||||
|
||||
|
@ -253,6 +269,12 @@ class Atom10Feed extends XMLStringer
|
|||
$this->id = $id;
|
||||
}
|
||||
|
||||
function setSelfLink($url, $type='application/atom+xml')
|
||||
{
|
||||
$this->selfLink = $url;
|
||||
$this->selfLinkType = $type;
|
||||
}
|
||||
|
||||
function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
|
|
|
@ -49,14 +49,42 @@ class AtomGroupNoticeFeed extends AtomNoticeFeed
|
|||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Group $group the group for the feed (optional)
|
||||
* @param Group $group the group for the feed
|
||||
* @param boolean $indent flag to turn indenting on or off
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function __construct($group = null, $indent = true) {
|
||||
function __construct($group, $indent = true) {
|
||||
parent::__construct($indent);
|
||||
$this->group = $group;
|
||||
|
||||
$title = sprintf(_("%s timeline"), $group->nickname);
|
||||
$this->setTitle($title);
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
$subtitle = sprintf(
|
||||
_('Updates from %1$s on %2$s!'),
|
||||
$group->nickname,
|
||||
$sitename
|
||||
);
|
||||
$this->setSubtitle($subtitle);
|
||||
|
||||
$avatar = $group->homepage_logo;
|
||||
$logo = ($avatar) ? $avatar : User_group::defaultLogo(AVATAR_PROFILE_SIZE);
|
||||
$this->setLogo($logo);
|
||||
|
||||
$this->setUpdated('now');
|
||||
|
||||
$self = common_local_url('ApiTimelineGroup',
|
||||
array('id' => $group->id,
|
||||
'format' => 'atom'));
|
||||
$this->setId($self);
|
||||
$this->setSelfLink($self);
|
||||
|
||||
$this->addAuthorRaw($group->asAtomAuthor());
|
||||
$this->setActivitySubject($group->asActivitySubject());
|
||||
|
||||
$this->addLink($group->homeUrl());
|
||||
}
|
||||
|
||||
function getGroup()
|
||||
|
|
|
@ -107,9 +107,19 @@ class AtomNoticeFeed extends Atom10Feed
|
|||
*/
|
||||
function addEntryFromNotice($notice)
|
||||
{
|
||||
$this->addEntryRaw($notice->asAtomEntry());
|
||||
$source = $this->showSource();
|
||||
$author = $this->showAuthor();
|
||||
|
||||
$this->addEntryRaw($notice->asAtomEntry(false, $source, $author));
|
||||
}
|
||||
|
||||
function showSource()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
function showAuthor()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -49,23 +49,71 @@ class AtomUserNoticeFeed extends AtomNoticeFeed
|
|||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param User $user the user for the feed (optional)
|
||||
* @param User $user the user for the feed
|
||||
* @param boolean $indent flag to turn indenting on or off
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
function __construct($user = null, $indent = true) {
|
||||
function __construct($user, $indent = true) {
|
||||
parent::__construct($indent);
|
||||
$this->user = $user;
|
||||
if (!empty($user)) {
|
||||
$profile = $user->getProfile();
|
||||
$this->addAuthor($profile->nickname, $user->uri);
|
||||
$this->setActivitySubject($profile->asActivityNoun('subject'));
|
||||
}
|
||||
|
||||
$title = sprintf(_("%s timeline"), $user->nickname);
|
||||
$this->setTitle($title);
|
||||
|
||||
$sitename = common_config('site', 'name');
|
||||
$subtitle = sprintf(
|
||||
_('Updates from %1$s on %2$s!'),
|
||||
$user->nickname, $sitename
|
||||
);
|
||||
$this->setSubtitle($subtitle);
|
||||
|
||||
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
|
||||
$logo = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE);
|
||||
$this->setLogo($logo);
|
||||
|
||||
$this->setUpdated('now');
|
||||
|
||||
$this->addLink(
|
||||
common_local_url(
|
||||
'showstream',
|
||||
array('nickname' => $user->nickname)
|
||||
)
|
||||
);
|
||||
|
||||
$self = common_local_url('ApiTimelineUser',
|
||||
array('id' => $user->id,
|
||||
'format' => 'atom'));
|
||||
$this->setId($self);
|
||||
$this->setSelfLink($self);
|
||||
|
||||
$this->addLink(
|
||||
common_local_url('sup', null, null, $user->id),
|
||||
array(
|
||||
'rel' => 'http://api.friendfeed.com/2008/03#sup',
|
||||
'type' => 'application/json'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
function showSource()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
function showAuthor()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
93
lib/grantroleform.php
Normal file
93
lib/grantroleform.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Form for granting a role
|
||||
*
|
||||
* 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 Form
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>, Brion Vibber <brion@status.net>
|
||||
* @copyright 2009-2010 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form for sandboxing a user
|
||||
*
|
||||
* @category Form
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*
|
||||
* @see UnSandboxForm
|
||||
*/
|
||||
|
||||
class GrantRoleForm extends ProfileActionForm
|
||||
{
|
||||
function __construct($role, $label, $writer, $profile, $r2args)
|
||||
{
|
||||
parent::__construct($writer, $profile, $r2args);
|
||||
$this->role = $role;
|
||||
$this->label = $label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action this form provides
|
||||
*
|
||||
* @return string Name of the action, lowercased.
|
||||
*/
|
||||
|
||||
function target()
|
||||
{
|
||||
return 'grantrole';
|
||||
}
|
||||
|
||||
/**
|
||||
* Title of the form
|
||||
*
|
||||
* @return string Title of the form, internationalized
|
||||
*/
|
||||
|
||||
function title()
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
function formData()
|
||||
{
|
||||
parent::formData();
|
||||
$this->out->hidden('role', $this->role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of the form
|
||||
*
|
||||
* @return string description of the form, internationalized
|
||||
*/
|
||||
|
||||
function description()
|
||||
{
|
||||
return sprintf(_('Grant this user the "%s" role'), $this->label);
|
||||
}
|
||||
}
|
93
lib/revokeroleform.php
Normal file
93
lib/revokeroleform.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
/**
|
||||
* StatusNet, the distributed open-source microblogging tool
|
||||
*
|
||||
* Form for revoking a role
|
||||
*
|
||||
* 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 Form
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>, Brion Vibber <brion@status.net>
|
||||
* @copyright 2009-2010 StatusNet, Inc.
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Form for sandboxing a user
|
||||
*
|
||||
* @category Form
|
||||
* @package StatusNet
|
||||
* @author Evan Prodromou <evan@status.net>
|
||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||
* @link http://status.net/
|
||||
*
|
||||
* @see UnSandboxForm
|
||||
*/
|
||||
|
||||
class RevokeRoleForm extends ProfileActionForm
|
||||
{
|
||||
function __construct($role, $label, $writer, $profile, $r2args)
|
||||
{
|
||||
parent::__construct($writer, $profile, $r2args);
|
||||
$this->role = $role;
|
||||
$this->label = $label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action this form provides
|
||||
*
|
||||
* @return string Name of the action, lowercased.
|
||||
*/
|
||||
|
||||
function target()
|
||||
{
|
||||
return 'revokerole';
|
||||
}
|
||||
|
||||
/**
|
||||
* Title of the form
|
||||
*
|
||||
* @return string Title of the form, internationalized
|
||||
*/
|
||||
|
||||
function title()
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
function formData()
|
||||
{
|
||||
parent::formData();
|
||||
$this->out->hidden('role', $this->role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of the form
|
||||
*
|
||||
* @return string description of the form, internationalized
|
||||
*/
|
||||
|
||||
function description()
|
||||
{
|
||||
return sprintf(_('Revoke the "%s" role from this user'), $this->label);
|
||||
}
|
||||
}
|
|
@ -58,5 +58,7 @@ class Right
|
|||
const EMAILONSUBSCRIBE = 'emailonsubscribe';
|
||||
const EMAILONFAVE = 'emailonfave';
|
||||
const MAKEGROUPADMIN = 'makegroupadmin';
|
||||
const GRANTROLE = 'grantrole';
|
||||
const REVOKEROLE = 'revokerole';
|
||||
}
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ class Router
|
|||
'groupblock', 'groupunblock',
|
||||
'sandbox', 'unsandbox',
|
||||
'silence', 'unsilence',
|
||||
'grantrole', 'revokerole',
|
||||
'repeat',
|
||||
'deleteuser',
|
||||
'geocode',
|
||||
|
@ -650,6 +651,7 @@ class Router
|
|||
$m->connect('admin/paths', array('action' => 'pathsadminpanel'));
|
||||
$m->connect('admin/sessions', array('action' => 'sessionsadminpanel'));
|
||||
$m->connect('admin/sitenotice', array('action' => 'sitenoticeadminpanel'));
|
||||
$m->connect('admin/snapshot', array('action' => 'snapshotadminpanel'));
|
||||
|
||||
$m->connect('getfile/:filename',
|
||||
array('action' => 'getfile'),
|
||||
|
|
|
@ -354,10 +354,10 @@ class StatusNet
|
|||
|
||||
class NoConfigException extends Exception
|
||||
{
|
||||
public $config_files;
|
||||
public $configFiles;
|
||||
|
||||
function __construct($msg, $config_files) {
|
||||
function __construct($msg, $configFiles) {
|
||||
parent::__construct($msg);
|
||||
$this->config_files = $config_files;
|
||||
$this->configFiles = $configFiles;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -346,6 +346,16 @@ class UserProfile extends Widget
|
|||
$this->out->elementEnd('ul');
|
||||
$this->out->elementEnd('li');
|
||||
}
|
||||
|
||||
if ($cur->hasRight(Right::GRANTROLE)) {
|
||||
$this->out->elementStart('li', 'entity_role');
|
||||
$this->out->element('p', null, _('User role'));
|
||||
$this->out->elementStart('ul');
|
||||
$this->roleButton('administrator', _m('role', 'Administrator'));
|
||||
$this->roleButton('moderator', _m('role', 'Moderator'));
|
||||
$this->out->elementEnd('ul');
|
||||
$this->out->elementEnd('li');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,6 +369,22 @@ class UserProfile extends Widget
|
|||
}
|
||||
}
|
||||
|
||||
function roleButton($role, $label)
|
||||
{
|
||||
list($action, $r2args) = $this->out->returnToArgs();
|
||||
$r2args['action'] = $action;
|
||||
|
||||
$this->out->elementStart('li', "entity_role_$role");
|
||||
if ($this->user->hasRole($role)) {
|
||||
$rf = new RevokeRoleForm($role, $label, $this->out, $this->profile, $r2args);
|
||||
$rf->show();
|
||||
} else {
|
||||
$rf = new GrantRoleForm($role, $label, $this->out, $this->profile, $r2args);
|
||||
$rf->show();
|
||||
}
|
||||
$this->out->elementEnd('li');
|
||||
}
|
||||
|
||||
function showRemoteSubscribeLink()
|
||||
{
|
||||
$url = common_local_url('remotesubscribe',
|
||||
|
|
|
@ -44,7 +44,9 @@ class OStatusPlugin extends Plugin
|
|||
$m->connect('.well-known/host-meta',
|
||||
array('action' => 'hostmeta'));
|
||||
$m->connect('main/xrd',
|
||||
array('action' => 'xrd'));
|
||||
array('action' => 'userxrd'));
|
||||
$m->connect('main/ownerxrd',
|
||||
array('action' => 'ownerxrd'));
|
||||
$m->connect('main/ostatus',
|
||||
array('action' => 'ostatusinit'));
|
||||
$m->connect('main/ostatus?nickname=:nickname',
|
||||
|
@ -111,7 +113,7 @@ class OStatusPlugin extends Plugin
|
|||
{
|
||||
if ($action instanceof ShowstreamAction) {
|
||||
$acct = 'acct:'. $action->profile->nickname .'@'. common_config('site', 'server');
|
||||
$url = common_local_url('xrd');
|
||||
$url = common_local_url('userxrd');
|
||||
$url.= '?uri='. $acct;
|
||||
|
||||
header('Link: <'.$url.'>; rel="'. Discovery::LRDD_REL.'"; type="application/xrd+xml"');
|
||||
|
|
|
@ -32,7 +32,7 @@ class HostMetaAction extends Action
|
|||
parent::handle();
|
||||
|
||||
$domain = common_config('site', 'server');
|
||||
$url = common_local_url('xrd');
|
||||
$url = common_local_url('userxrd');
|
||||
$url.= '?uri={uri}';
|
||||
|
||||
$xrd = new XRD();
|
||||
|
|
|
@ -72,9 +72,9 @@ class OStatusGroupAction extends OStatusSubAction
|
|||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->input('profile',
|
||||
_m('Group profile URL'),
|
||||
_m('Join group'),
|
||||
$this->profile_uri,
|
||||
_m('Enter the profile URL of a group on another StatusNet site'));
|
||||
_m("OStatus group's address, like http://example.net/group/nickname"));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
|
||||
|
|
|
@ -62,9 +62,9 @@ class OStatusSubAction extends Action
|
|||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->input('profile',
|
||||
_m('Address or profile URL'),
|
||||
_m('Subscribe to'),
|
||||
$this->profile_uri,
|
||||
_m('Enter the profile URL of a PubSubHubbub-enabled feed'));
|
||||
_m("OStatus user's address, like nickname@example.com or http://example.net/nickname"));
|
||||
$this->elementEnd('li');
|
||||
$this->elementEnd('ul');
|
||||
|
||||
|
@ -244,25 +244,33 @@ class OStatusSubAction extends Action
|
|||
} else if (Validate::uri($this->profile_uri)) {
|
||||
$this->oprofile = Ostatus_profile::ensureProfile($this->profile_uri);
|
||||
} else {
|
||||
$this->error = _m("Invalid address format.");
|
||||
$this->error = _m("Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname");
|
||||
common_debug('Invalid address format.', __FILE__);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (FeedSubBadURLException $e) {
|
||||
$this->error = _m('Invalid URL or could not reach server.');
|
||||
$this->error = _m("Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname");
|
||||
common_debug('Invalid URL or could not reach server.', __FILE__);
|
||||
} catch (FeedSubBadResponseException $e) {
|
||||
$this->error = _m('Cannot read feed; server returned error.');
|
||||
$this->error = _m("Sorry, we could not reach that feed. Please try that OStatus address again later.");
|
||||
common_debug('Cannot read feed; server returned error.', __FILE__);
|
||||
} catch (FeedSubEmptyException $e) {
|
||||
$this->error = _m('Cannot read feed; server returned an empty page.');
|
||||
$this->error = _m("Sorry, we could not reach that feed. Please try that OStatus address again later.");
|
||||
common_debug('Cannot read feed; server returned an empty page.', __FILE__);
|
||||
} catch (FeedSubBadHTMLException $e) {
|
||||
$this->error = _m('Bad HTML, could not find feed link.');
|
||||
$this->error = _m("Sorry, we could not reach that feed. Please try that OStatus address again later.");
|
||||
common_debug('Bad HTML, could not find feed link.', __FILE__);
|
||||
} catch (FeedSubNoFeedException $e) {
|
||||
$this->error = _m('Could not find a feed linked from this URL.');
|
||||
$this->error = _m("Sorry, we could not reach that feed. Please try that OStatus address again later.");
|
||||
common_debug('Could not find a feed linked from this URL.', __FILE__);
|
||||
} catch (FeedSubUnrecognizedTypeException $e) {
|
||||
$this->error = _m('Not a recognized feed type.');
|
||||
} catch (FeedSubException $e) {
|
||||
$this->error = _m("Sorry, we could not reach that feed. Please try that OStatus address again later.");
|
||||
common_debug('Not a recognized feed type.', __FILE__);
|
||||
} catch (Exception $e) {
|
||||
// Any new ones we forgot about
|
||||
$this->error = sprintf(_m('Bad feed URL: %s %s'), get_class($e), $e->getMessage());
|
||||
$this->error = _m("Sorry, we could not reach that address. Please make sure that the OStatus address is like nickname@example.com or http://example.net/nickname");
|
||||
common_debug(sprintf('Bad feed URL: %s %s', get_class($e), $e->getMessage()), __FILE__);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -315,7 +323,6 @@ class OStatusSubAction extends Action
|
|||
if ($this->pullRemoteProfile()) {
|
||||
$this->validateRemoteProfile();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -391,7 +398,7 @@ class OStatusSubAction extends Action
|
|||
function title()
|
||||
{
|
||||
// TRANS: Page title for OStatus remote subscription form
|
||||
return _m('Authorize subscription');
|
||||
return _m('Confirm');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
56
plugins/OStatus/actions/ownerxrd.php
Normal file
56
plugins/OStatus/actions/ownerxrd.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
/*
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
* Copyright (C) 2010, StatusNet, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @package OStatusPlugin
|
||||
* @maintainer James Walker <james@status.net>
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
|
||||
|
||||
class OwnerxrdAction extends XrdAction
|
||||
{
|
||||
|
||||
public $uri;
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
$this->user = User::siteOwner();
|
||||
|
||||
if (!$this->user) {
|
||||
$this->clientError(_('No such user.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
$nick = common_canonical_nickname($this->user->nickname);
|
||||
$acct = 'acct:' . $nick . '@' . common_config('site', 'server');
|
||||
|
||||
$this->xrd = new XRD();
|
||||
|
||||
// Check to see if a $config['webfinger']['owner'] has been set
|
||||
if ($owner = common_config('webfinger', 'owner')) {
|
||||
$this->xrd->subject = Discovery::normalize($owner);
|
||||
$this->xrd->alias[] = $acct;
|
||||
} else {
|
||||
$this->xrd->subject = $acct;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
48
plugins/OStatus/actions/userxrd.php
Normal file
48
plugins/OStatus/actions/userxrd.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
/*
|
||||
* StatusNet - the distributed open-source microblogging tool
|
||||
* Copyright (C) 2010, StatusNet, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @package OStatusPlugin
|
||||
* @maintainer James Walker <james@status.net>
|
||||
*/
|
||||
|
||||
if (!defined('STATUSNET')) { exit(1); }
|
||||
|
||||
class UserxrdAction extends XrdAction
|
||||
{
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
|
||||
$this->uri = $this->trimmed('uri');
|
||||
$acct = Discovery::normalize($this->uri);
|
||||
|
||||
list($nick, $domain) = explode('@', substr(urldecode($acct), 5));
|
||||
$nick = common_canonical_nickname($nick);
|
||||
|
||||
$this->user = User::staticGet('nickname', $nick);
|
||||
if (!$this->user) {
|
||||
$this->clientError(_('No such user.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1267,6 +1267,11 @@ class Ostatus_profile extends Memcached_DataObject
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $addr webfinger address
|
||||
* @return Ostatus_profile
|
||||
* @throws Exception on error conditions
|
||||
*/
|
||||
public static function ensureWebfinger($addr)
|
||||
{
|
||||
// First, try the cache
|
||||
|
@ -1275,7 +1280,8 @@ class Ostatus_profile extends Memcached_DataObject
|
|||
|
||||
if ($uri !== false) {
|
||||
if (is_null($uri)) {
|
||||
return null;
|
||||
// Negative cache entry
|
||||
throw new Exception('Not a valid webfinger address.');
|
||||
}
|
||||
$oprofile = Ostatus_profile::staticGet('uri', $uri);
|
||||
if (!empty($oprofile)) {
|
||||
|
@ -1299,20 +1305,24 @@ class Ostatus_profile extends Memcached_DataObject
|
|||
try {
|
||||
$result = $disco->lookup($addr);
|
||||
} catch (Exception $e) {
|
||||
// Save negative cache entry so we don't waste time looking it up again.
|
||||
// @fixme distinguish temporary failures?
|
||||
self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), null);
|
||||
return null;
|
||||
throw new Exception('Not a valid webfinger address.');
|
||||
}
|
||||
|
||||
$hints = array('webfinger' => $addr);
|
||||
|
||||
foreach ($result->links as $link) {
|
||||
switch ($link['rel']) {
|
||||
case Discovery::PROFILEPAGE:
|
||||
$profileUrl = $link['href'];
|
||||
$hints['profileurl'] = $profileUrl = $link['href'];
|
||||
break;
|
||||
case Salmon::NS_REPLIES:
|
||||
$salmonEndpoint = $link['href'];
|
||||
$hints['salmon'] = $salmonEndpoint = $link['href'];
|
||||
break;
|
||||
case Discovery::UPDATESFROM:
|
||||
$feedUrl = $link['href'];
|
||||
$hints['feedurl'] = $feedUrl = $link['href'];
|
||||
break;
|
||||
case Discovery::HCARD:
|
||||
$hcardUrl = $link['href'];
|
||||
|
@ -1323,11 +1333,6 @@ class Ostatus_profile extends Memcached_DataObject
|
|||
}
|
||||
}
|
||||
|
||||
$hints = array('webfinger' => $addr,
|
||||
'profileurl' => $profileUrl,
|
||||
'feedurl' => $feedUrl,
|
||||
'salmon' => $salmonEndpoint);
|
||||
|
||||
if (isset($hcardUrl)) {
|
||||
$hcardHints = self::slurpHcard($hcardUrl);
|
||||
// Note: Webfinger > hcard
|
||||
|
@ -1410,7 +1415,7 @@ class Ostatus_profile extends Memcached_DataObject
|
|||
return $oprofile;
|
||||
}
|
||||
|
||||
return null;
|
||||
throw new Exception("Couldn't find a valid profile for '$addr'");
|
||||
}
|
||||
|
||||
function saveHTMLFile($title, $rendered)
|
||||
|
|
|
@ -156,17 +156,31 @@ class MagicEnvelope
|
|||
public function verify($env)
|
||||
{
|
||||
if ($env['alg'] != 'RSA-SHA256') {
|
||||
common_log(LOG_DEBUG, "Salmon error: bad algorithm");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($env['encoding'] != MagicEnvelope::ENCODING) {
|
||||
common_log(LOG_DEBUG, "Salmon error: bad encoding");
|
||||
return false;
|
||||
}
|
||||
|
||||
$text = base64_decode($env['data']);
|
||||
$signer_uri = $this->getAuthor($text);
|
||||
|
||||
$verifier = Magicsig::fromString($this->getKeyPair($signer_uri));
|
||||
try {
|
||||
$keypair = $this->getKeyPair($signer_uri);
|
||||
} catch (Exception $e) {
|
||||
common_log(LOG_DEBUG, "Salmon error: ".$e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
$verifier = Magicsig::fromString($keypair);
|
||||
|
||||
if (!$verifier) {
|
||||
common_log(LOG_DEBUG, "Salmon error: unable to parse keypair");
|
||||
return false;
|
||||
}
|
||||
|
||||
return $verifier->verify($env['data'], $env['sig']);
|
||||
}
|
||||
|
|
|
@ -164,46 +164,21 @@ class OStatusQueueHandler extends QueueHandler
|
|||
*/
|
||||
function userFeedForNotice()
|
||||
{
|
||||
// @fixme this feels VERY hacky...
|
||||
// should probably be a cleaner way to do it
|
||||
$atom = new AtomUserNoticeFeed($this->user);
|
||||
$atom->addEntryFromNotice($this->notice);
|
||||
$feed = $atom->getString();
|
||||
|
||||
ob_start();
|
||||
$api = new ApiTimelineUserAction();
|
||||
$api->prepare(array('id' => $this->notice->profile_id,
|
||||
'format' => 'atom',
|
||||
'max_id' => $this->notice->id,
|
||||
'since_id' => $this->notice->id - 1));
|
||||
$api->showTimeline();
|
||||
$feed = ob_get_clean();
|
||||
|
||||
// ...and override the content-type back to something normal... eww!
|
||||
// hope there's no other headers that got set while we weren't looking.
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
|
||||
common_log(LOG_DEBUG, $feed);
|
||||
return $feed;
|
||||
}
|
||||
|
||||
function groupFeedForNotice($group_id)
|
||||
{
|
||||
// @fixme this feels VERY hacky...
|
||||
// should probably be a cleaner way to do it
|
||||
$group = User_group::staticGet('id', $group_id);
|
||||
|
||||
ob_start();
|
||||
$api = new ApiTimelineGroupAction();
|
||||
$args = array('id' => $group_id,
|
||||
'format' => 'atom',
|
||||
'max_id' => $this->notice->id,
|
||||
'since_id' => $this->notice->id - 1);
|
||||
$api->prepare($args);
|
||||
$api->handle($args);
|
||||
$feed = ob_get_clean();
|
||||
$atom = new AtomGroupNoticeFeed($group);
|
||||
$atom->addEntryFromNotice($this->notice);
|
||||
$feed = $atom->getString();
|
||||
|
||||
// ...and override the content-type back to something normal... eww!
|
||||
// hope there's no other headers that got set while we weren't looking.
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
|
||||
common_log(LOG_DEBUG, $feed);
|
||||
return $feed;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,6 +57,9 @@ class XRD
|
|||
throw new Exception("Invalid XML");
|
||||
}
|
||||
$xrd_element = $dom->getElementsByTagName('XRD')->item(0);
|
||||
if (!$xrd_element) {
|
||||
throw new Exception("Invalid XML, missing XRD root");
|
||||
}
|
||||
|
||||
// Check for host-meta host
|
||||
$host = $xrd_element->getElementsByTagName('Host')->item(0);
|
||||
|
|
|
@ -29,31 +29,23 @@ class XrdAction extends Action
|
|||
|
||||
public $uri;
|
||||
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
public $user;
|
||||
|
||||
$this->uri = $this->trimmed('uri');
|
||||
|
||||
return true;
|
||||
}
|
||||
public $xrd;
|
||||
|
||||
function handle()
|
||||
{
|
||||
$acct = Discovery::normalize($this->uri);
|
||||
$nick = $this->user->nickname;
|
||||
|
||||
$xrd = new XRD();
|
||||
|
||||
list($nick, $domain) = explode('@', substr(urldecode($acct), 5));
|
||||
$nick = common_canonical_nickname($nick);
|
||||
|
||||
$this->user = User::staticGet('nickname', $nick);
|
||||
if (!$this->user) {
|
||||
$this->clientError(_('No such user.'), 404);
|
||||
return false;
|
||||
if (empty($this->xrd)) {
|
||||
$xrd = new XRD();
|
||||
} else {
|
||||
$xrd = $this->xrd;
|
||||
}
|
||||
|
||||
$xrd->subject = $this->uri;
|
||||
if (empty($xrd->subject)) {
|
||||
$xrd->subject = Discovery::normalize($this->uri);
|
||||
}
|
||||
$xrd->alias[] = common_profile_url($nick);
|
||||
$xrd->links[] = array('rel' => Discovery::PROFILEPAGE,
|
||||
'type' => 'text/html',
|
|
@ -52,7 +52,8 @@ margin-bottom:0;
|
|||
width:405px;
|
||||
}
|
||||
|
||||
.aside #entity_subscriptions .more {
|
||||
.aside #entity_subscriptions .more,
|
||||
.aside #entity_groups .more {
|
||||
float:left;
|
||||
}
|
||||
|
||||
|
|
131
tests/UserFeedParseTest.php
Normal file
131
tests/UserFeedParseTest.php
Normal file
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
|
||||
print "This script must be run from the command line\n";
|
||||
exit();
|
||||
}
|
||||
|
||||
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
|
||||
define('STATUSNET', true);
|
||||
|
||||
require_once INSTALLDIR . '/lib/common.php';
|
||||
|
||||
class UserFeedParseTests extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testFeed1()
|
||||
{
|
||||
global $_testfeed1;
|
||||
$dom = DOMDocument::loadXML($_testfeed1);
|
||||
$this->assertFalse(empty($dom));
|
||||
|
||||
$entries = $dom->getElementsByTagName('entry');
|
||||
|
||||
$entry1 = $entries->item(0);
|
||||
$this->assertFalse(empty($entry1));
|
||||
|
||||
$feedEl = $dom->getElementsByTagName('feed')->item(0);
|
||||
$this->assertFalse(empty($feedEl));
|
||||
|
||||
// Test actor (from activity:subject)
|
||||
|
||||
$act1 = new Activity($entry1, $feedEl);
|
||||
$this->assertFalse(empty($act1));
|
||||
$this->assertFalse(empty($act1->actor));
|
||||
$this->assertEquals($act1->actor->type, ActivityObject::PERSON);
|
||||
$this->assertEquals($act1->actor->title, 'Zach Copley');
|
||||
$this->assertEquals($act1->actor->id, 'http://localhost/statusnet/user/1');
|
||||
$this->assertEquals($act1->actor->link, 'http://localhost/statusnet/zach');
|
||||
|
||||
$avatars = $act1->actor->avatarLinks;
|
||||
|
||||
$this->assertEquals(
|
||||
$avatars[0]->url,
|
||||
'http://localhost/statusnet/theme/default/default-avatar-profile.png'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$avatars[1]->url,
|
||||
'http://localhost/statusnet/theme/default/default-avatar-stream.png'
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
$avatars[2]->url,
|
||||
'http://localhost/statusnet/theme/default/default-avatar-mini.png'
|
||||
);
|
||||
|
||||
$this->assertEquals($act1->actor->displayName, 'Zach Copley');
|
||||
|
||||
$poco = $act1->actor->poco;
|
||||
$this->assertEquals($poco->preferredUsername, 'zach');
|
||||
$this->assertEquals($poco->address->formatted, 'El Cerrito, CA');
|
||||
$this->assertEquals($poco->urls[0]->type, 'homepage');
|
||||
$this->assertEquals($poco->urls[0]->value, 'http://zach.copley.name');
|
||||
$this->assertEquals($poco->urls[0]->primary, 'true');
|
||||
$this->assertEquals($poco->note, 'Zach Hack Attack');
|
||||
|
||||
// test the post
|
||||
|
||||
//var_export($act1);
|
||||
$this->assertEquals($act1->object->type, 'http://activitystrea.ms/schema/1.0/note');
|
||||
$this->assertEquals($act1->object->title, 'And now for something completely insane...');
|
||||
|
||||
$this->assertEquals($act1->object->content, 'And now for something completely insane...');
|
||||
$this->assertEquals($act1->object->id, 'http://localhost/statusnet/notice/3');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$_testfeed1 = <<<TESTFEED1
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:georss="http://www.georss.org/georss" xmlns:activity="http://activitystrea.ms/spec/1.0/" xmlns:media="http://purl.org/syndication/atommedia" xmlns:poco="http://portablecontacts.net/spec/1.0" xmlns:ostatus="http://ostatus.org/schema/1.0">
|
||||
<id>http://localhost/statusnet/api/statuses/user_timeline/1.atom</id>
|
||||
<title>zach timeline</title>
|
||||
<subtitle>Updates from zach on Zach Dev!</subtitle>
|
||||
<logo>http://localhost/statusnet/theme/default/default-avatar-profile.png</logo>
|
||||
<updated>2010-03-04T01:41:14+00:00</updated>
|
||||
<author>
|
||||
<name>zach</name>
|
||||
<uri>http://localhost/statusnet/user/1</uri>
|
||||
|
||||
</author>
|
||||
<link href="http://localhost/statusnet/zach" rel="alternate" type="text/html"/>
|
||||
<link href="http://localhost/statusnet/main/sup#1" rel="http://api.friendfeed.com/2008/03#sup" type="application/json"/>
|
||||
<link href="http://localhost/statusnet/main/push/hub" rel="hub"/>
|
||||
<link href="http://localhost/statusnet/main/salmon/user/1" rel="http://salmon-protocol.org/ns/salmon-replies"/>
|
||||
<link href="http://localhost/statusnet/main/salmon/user/1" rel="http://salmon-protocol.org/ns/salmon-mention"/>
|
||||
<link href="http://localhost/statusnet/api/statuses/user_timeline/1.atom" rel="self" type="application/atom+xml"/>
|
||||
<activity:subject>
|
||||
<activity:object-type>http://activitystrea.ms/schema/1.0/person</activity:object-type>
|
||||
<id>http://localhost/statusnet/user/1</id>
|
||||
<title>Zach Copley</title>
|
||||
<link rel="alternate" type="text/html" href="http://localhost/statusnet/zach"/>
|
||||
<link rel="avatar" type="image/png" media:width="96" media:height="96" href="http://localhost/statusnet/theme/default/default-avatar-profile.png"/>
|
||||
<link rel="avatar" type="image/png" media:width="48" media:height="48" href="http://localhost/statusnet/theme/default/default-avatar-stream.png"/>
|
||||
<link rel="avatar" type="image/png" media:width="24" media:height="24" href="http://localhost/statusnet/theme/default/default-avatar-mini.png"/>
|
||||
|
||||
<poco:preferredUsername>zach</poco:preferredUsername>
|
||||
<poco:displayName>Zach Copley</poco:displayName>
|
||||
<poco:note>Zach Hack Attack</poco:note>
|
||||
<poco:address>
|
||||
<poco:formatted>El Cerrito, CA</poco:formatted>
|
||||
</poco:address>
|
||||
<poco:urls>
|
||||
<poco:type>homepage</poco:type>
|
||||
<poco:value>http://zach.copley.name</poco:value>
|
||||
<poco:primary>true</poco:primary>
|
||||
|
||||
</poco:urls>
|
||||
</activity:subject>
|
||||
<entry>
|
||||
<title>And now for something completely insane...</title>
|
||||
<link rel="alternate" type="text/html" href="http://localhost/statusnet/notice/3"/>
|
||||
<id>http://localhost/statusnet/notice/3</id>
|
||||
<published>2010-03-04T01:41:07+00:00</published>
|
||||
<updated>2010-03-04T01:41:07+00:00</updated>
|
||||
<link rel="ostatus:conversation" href="http://localhost/statusnet/conversation/3"/>
|
||||
<content type="html">And now for something completely insane...</content>
|
||||
</entry>
|
||||
|
||||
</feed>
|
||||
TESTFEED1;
|
|
@ -771,10 +771,12 @@ display:none;
|
|||
text-align:center;
|
||||
}
|
||||
|
||||
.entity_moderation {
|
||||
.entity_moderation,
|
||||
.entity_role {
|
||||
position:relative;
|
||||
}
|
||||
.entity_moderation p {
|
||||
.entity_moderation p,
|
||||
.entity_role p {
|
||||
border-radius:4px;
|
||||
-moz-border-radius:4px;
|
||||
-webkit-border-radius:4px;
|
||||
|
@ -782,13 +784,14 @@ font-weight:bold;
|
|||
padding-bottom:2px;
|
||||
margin-bottom:7px;
|
||||
}
|
||||
.entity_moderation ul {
|
||||
.entity_moderation ul,
|
||||
.entity_role ul {
|
||||
display:none;
|
||||
}
|
||||
.entity_moderation:hover ul {
|
||||
.entity_moderation:hover ul,
|
||||
.entity_role:hover ul {
|
||||
display:block;
|
||||
min-width:21%;
|
||||
width:100%;
|
||||
width:110%;
|
||||
padding:11px;
|
||||
position:absolute;
|
||||
top:-1px;
|
||||
|
|
|
@ -45,6 +45,11 @@
|
|||
White pin with green background
|
||||
White underscore with green background
|
||||
White C with green background
|
||||
White magic wand with green background
|
||||
Green badge with white background
|
||||
Green sandbox with white background
|
||||
Green speech bubble broken with white background
|
||||
Green person with tie with white background
|
||||
*/
|
||||
|
||||
Created by various authors
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 4.0 KiB |
|
@ -49,6 +49,7 @@ box-shadow:3px 3px 7px rgba(194, 194, 194, 0.3);
|
|||
.pagination .nav_next a,
|
||||
.form_settings fieldset fieldset,
|
||||
.entity_moderation:hover ul,
|
||||
.entity_role:hover ul,
|
||||
.dialogbox {
|
||||
border-color:#DDDDDD;
|
||||
}
|
||||
|
@ -67,6 +68,7 @@ input.submit,
|
|||
.entity_actions a,
|
||||
.entity_actions input,
|
||||
.entity_moderation p,
|
||||
.entity_role p,
|
||||
button {
|
||||
box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
|
||||
-moz-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
|
||||
|
@ -127,7 +129,8 @@ a,
|
|||
.notice-options input,
|
||||
.entity_actions a,
|
||||
.entity_actions input,
|
||||
.entity_moderation p {
|
||||
.entity_moderation p,
|
||||
.entity_role p {
|
||||
color:#002FA7;
|
||||
}
|
||||
|
||||
|
@ -190,6 +193,9 @@ button.close,
|
|||
.entity_sandbox input.submit,
|
||||
.entity_silence input.submit,
|
||||
.entity_delete input.submit,
|
||||
.entity_role p,
|
||||
.entity_role_administrator input.submit,
|
||||
.entity_role_moderator input.submit,
|
||||
.notice-options .repeated,
|
||||
.form_notice label[for=notice_data-geo],
|
||||
button.minimize,
|
||||
|
@ -229,6 +235,7 @@ border-color:transparent;
|
|||
#site_nav_local_views .current a,
|
||||
.entity_send-a-message .form_notice,
|
||||
.entity_moderation:hover ul,
|
||||
.entity_role:hover ul,
|
||||
.dialogbox {
|
||||
background-color:#FFFFFF;
|
||||
}
|
||||
|
@ -319,6 +326,7 @@ background-position: 5px -852px;
|
|||
}
|
||||
.entity_send-a-message .form_notice,
|
||||
.entity_moderation:hover ul,
|
||||
.entity_role:hover ul,
|
||||
.dialogbox {
|
||||
box-shadow:3px 7px 5px rgba(194, 194, 194, 0.7);
|
||||
-moz-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.7);
|
||||
|
@ -350,6 +358,27 @@ background-position: 5px -1445px;
|
|||
.entity_delete input.submit {
|
||||
background-position: 5px -1511px;
|
||||
}
|
||||
.entity_sandbox .form_user_unsandbox input.submit {
|
||||
background-position: 5px -2568px;
|
||||
}
|
||||
.entity_silence .form_user_unsilence input.submit {
|
||||
background-position: 5px -2633px;
|
||||
}
|
||||
.entity_role p {
|
||||
background-position: 5px -2436px;
|
||||
}
|
||||
.entity_role_administrator .form_user_grantrole input.submit {
|
||||
background-position: 5px -983px;
|
||||
}
|
||||
.entity_role_moderator .form_user_grantrole input.submit {
|
||||
background-position: 5px -1313px;
|
||||
}
|
||||
.entity_role_administrator .form_user_revokerole input.submit {
|
||||
background-position: 5px -2699px;
|
||||
}
|
||||
.entity_role_moderator .form_user_revokerole input.submit {
|
||||
background-position: 5px -2501px;
|
||||
}
|
||||
.form_reset_key input.submit {
|
||||
background-position: 5px -1973px;
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ box-shadow:3px 3px 7px rgba(194, 194, 194, 0.3);
|
|||
.pagination .nav_next a,
|
||||
.form_settings fieldset fieldset,
|
||||
.entity_moderation:hover ul,
|
||||
.entity_role:hover ul,
|
||||
.dialogbox {
|
||||
border-color:#DDDDDD;
|
||||
}
|
||||
|
@ -67,6 +68,7 @@ input.submit,
|
|||
.entity_actions a,
|
||||
.entity_actions input,
|
||||
.entity_moderation p,
|
||||
.entity_role p,
|
||||
button {
|
||||
box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
|
||||
-moz-box-shadow:3px 3px 3px rgba(194, 194, 194, 0.3);
|
||||
|
@ -128,7 +130,8 @@ a,
|
|||
.notice-options input,
|
||||
.entity_actions a,
|
||||
.entity_actions input,
|
||||
.entity_moderation p {
|
||||
.entity_moderation p,
|
||||
.entity_role p {
|
||||
color:#002FA7;
|
||||
}
|
||||
|
||||
|
@ -191,6 +194,9 @@ button.close,
|
|||
.entity_sandbox input.submit,
|
||||
.entity_silence input.submit,
|
||||
.entity_delete input.submit,
|
||||
.entity_role p,
|
||||
.entity_role_administrator input.submit,
|
||||
.entity_role_moderator input.submit,
|
||||
.notice-options .repeated,
|
||||
.form_notice label[for=notice_data-geo],
|
||||
button.minimize,
|
||||
|
@ -230,6 +236,7 @@ border-color:transparent;
|
|||
#site_nav_local_views .current a,
|
||||
.entity_send-a-message .form_notice,
|
||||
.entity_moderation:hover ul,
|
||||
.entity_role:hover ul,
|
||||
.dialogbox {
|
||||
background-color:#FFFFFF;
|
||||
}
|
||||
|
@ -319,6 +326,7 @@ background-position: 5px -852px;
|
|||
}
|
||||
.entity_send-a-message .form_notice,
|
||||
.entity_moderation:hover ul,
|
||||
.entity_role:hover ul,
|
||||
.dialogbox {
|
||||
box-shadow:3px 7px 5px rgba(194, 194, 194, 0.7);
|
||||
-moz-box-shadow:3px 7px 5px rgba(194, 194, 194, 0.7);
|
||||
|
@ -350,6 +358,27 @@ background-position: 5px -1445px;
|
|||
.entity_delete input.submit {
|
||||
background-position: 5px -1511px;
|
||||
}
|
||||
.entity_sandbox .form_user_unsandbox input.submit {
|
||||
background-position: 5px -2568px;
|
||||
}
|
||||
.entity_silence .form_user_unsilence input.submit {
|
||||
background-position: 5px -2633px;
|
||||
}
|
||||
.entity_role p {
|
||||
background-position: 5px -2436px;
|
||||
}
|
||||
.entity_role_administrator .form_user_grantrole input.submit {
|
||||
background-position: 5px -983px;
|
||||
}
|
||||
.entity_role_moderator .form_user_grantrole input.submit {
|
||||
background-position: 5px -1313px;
|
||||
}
|
||||
.entity_role_administrator .form_user_revokerole input.submit {
|
||||
background-position: 5px -2699px;
|
||||
}
|
||||
.entity_role_moderator .form_user_revokerole input.submit {
|
||||
background-position: 5px -2501px;
|
||||
}
|
||||
.form_reset_key input.submit {
|
||||
background-position: 5px -1973px;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user