Merge branch '0.9.x' into 1.0.x
Conflicts: lib/queuemanager.php
This commit is contained in:
commit
914bc9f9c5
9
README
9
README
@ -1492,6 +1492,15 @@ disabled: whether to enable this command. If enabled, users who send
|
|||||||
should enable it only after you've convinced yourself that
|
should enable it only after you've convinced yourself that
|
||||||
it is safe. Default is 'false'.
|
it is safe. Default is 'false'.
|
||||||
|
|
||||||
|
singleuser
|
||||||
|
----------
|
||||||
|
|
||||||
|
If an installation has only one user, this can simplify a lot of the
|
||||||
|
interface. It also makes the user's profile the root URL.
|
||||||
|
|
||||||
|
enabled: Whether to run in "single user mode". Default false.
|
||||||
|
nickname: nickname of the single user.
|
||||||
|
|
||||||
Plugins
|
Plugins
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
192
actions/accessadminpanel.php
Normal file
192
actions/accessadminpanel.php
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Site access 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Administer site access settings
|
||||||
|
*
|
||||||
|
* @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 AccessadminpanelAction extends AdminPanelAction
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the page title
|
||||||
|
*
|
||||||
|
* @return string page title
|
||||||
|
*/
|
||||||
|
|
||||||
|
function title()
|
||||||
|
{
|
||||||
|
return _('Access');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instructions for using this form.
|
||||||
|
*
|
||||||
|
* @return string instructions
|
||||||
|
*/
|
||||||
|
|
||||||
|
function getInstructions()
|
||||||
|
{
|
||||||
|
return _('Site access settings');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the site admin panel form
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function showForm()
|
||||||
|
{
|
||||||
|
$form = new AccessAdminPanelForm($this);
|
||||||
|
$form->show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save settings from the form
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function saveSettings()
|
||||||
|
{
|
||||||
|
static $booleans = array('site' => array('private', 'inviteonly', 'closed'));
|
||||||
|
|
||||||
|
foreach ($booleans as $section => $parts) {
|
||||||
|
foreach ($parts as $setting) {
|
||||||
|
$values[$section][$setting] = ($this->boolean($setting)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = new Config();
|
||||||
|
|
||||||
|
$config->query('BEGIN');
|
||||||
|
|
||||||
|
foreach ($booleans as $section => $parts) {
|
||||||
|
foreach ($parts as $setting) {
|
||||||
|
Config::save($section, $setting, $values[$section][$setting]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$config->query('COMMIT');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class AccessAdminPanelForm extends AdminForm
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* ID of the form
|
||||||
|
*
|
||||||
|
* @return int ID of the form
|
||||||
|
*/
|
||||||
|
|
||||||
|
function id()
|
||||||
|
{
|
||||||
|
return 'form_site_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('accessadminpanel');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data elements of the form
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function formData()
|
||||||
|
{
|
||||||
|
$this->out->elementStart('fieldset', array('id' => 'settings_admin_access'));
|
||||||
|
$this->out->element('legend', null, _('Registration'));
|
||||||
|
$this->out->elementStart('ul', 'form_data');
|
||||||
|
$this->li();
|
||||||
|
$this->out->checkbox('private', _('Private'),
|
||||||
|
(bool) $this->value('private'),
|
||||||
|
_('Prohibit anonymous users (not logged in) from viewing site?'));
|
||||||
|
$this->unli();
|
||||||
|
|
||||||
|
$this->li();
|
||||||
|
$this->out->checkbox('inviteonly', _('Invite only'),
|
||||||
|
(bool) $this->value('inviteonly'),
|
||||||
|
_('Make registration invitation only.'));
|
||||||
|
$this->unli();
|
||||||
|
|
||||||
|
$this->li();
|
||||||
|
$this->out->checkbox('closed', _('Closed'),
|
||||||
|
(bool) $this->value('closed'),
|
||||||
|
_('Disable new registrations.'));
|
||||||
|
$this->unli();
|
||||||
|
$this->out->elementEnd('ul');
|
||||||
|
$this->out->elementEnd('fieldset');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action elements
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function formActions()
|
||||||
|
{
|
||||||
|
$this->out->submit('submit', _('Save'), 'submit', null, _('Save access settings'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -105,7 +105,22 @@ class ApiAccountRateLimitStatusAction extends ApiBareAuthAction
|
|||||||
print json_encode($out);
|
print json_encode($out);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->endDocument($this->format);
|
$this->endDocument($this->format);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -116,4 +116,19 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,6 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether this API resource requires auth. Overloaded to look
|
* Determines whether this API resource requires auth. Overloaded to look
|
||||||
* return true in case source_id and source_screen_name are both empty
|
* return true in case source_id and source_screen_name are both empty
|
||||||
@ -165,4 +164,19 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -119,4 +119,19 @@ class ApiGroupIsMemberAction extends ApiBareAuthAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -158,4 +158,19 @@ class ApiGroupShowAction extends ApiPrivateAuthAction
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -92,5 +92,20 @@ class ApiHelpTestAction extends ApiPrivateAuthAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ class ApiOauthAccessTokenAction extends ApiOauthAction
|
|||||||
$atok = $server->fetch_access_token($req);
|
$atok = $server->fetch_access_token($req);
|
||||||
|
|
||||||
} catch (OAuthException $e) {
|
} catch (OAuthException $e) {
|
||||||
common_log(LOG_WARN, 'API OAuthException - ' . $e->getMessage());
|
common_log(LOG_WARNING, 'API OAuthException - ' . $e->getMessage());
|
||||||
common_debug(var_export($req, true));
|
common_debug(var_export($req, true));
|
||||||
$this->outputError($e->getMessage());
|
$this->outputError($e->getMessage());
|
||||||
return;
|
return;
|
||||||
|
@ -167,7 +167,7 @@ class ApiOauthAuthorizeAction extends ApiOauthAction
|
|||||||
|
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
common_log_db_error($appUser, 'DELETE', __FILE__);
|
common_log_db_error($appUser, 'DELETE', __FILE__);
|
||||||
throw new ServerException(_('DB error deleting OAuth app user.'));
|
throw new ServerException(_('Database error deleting OAuth application user.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,7 +193,7 @@ class ApiOauthAuthorizeAction extends ApiOauthAction
|
|||||||
|
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
common_log_db_error($appUser, 'INSERT', __FILE__);
|
common_log_db_error($appUser, 'INSERT', __FILE__);
|
||||||
throw new ServerException(_('DB error inserting OAuth app user.'));
|
throw new ServerException(_('Database error inserting OAuth application user.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class ApiOauthRequestTokenAction extends ApiOauthAction
|
|||||||
$token = $server->fetch_request_token($req);
|
$token = $server->fetch_request_token($req);
|
||||||
print $token;
|
print $token;
|
||||||
} catch (OAuthException $e) {
|
} catch (OAuthException $e) {
|
||||||
common_log(LOG_WARN, 'API OAuthException - ' . $e->getMessage());
|
common_log(LOG_WARNING, 'API OAuthException - ' . $e->getMessage());
|
||||||
header('HTTP/1.1 401 Unauthorized');
|
header('HTTP/1.1 401 Unauthorized');
|
||||||
header('Content-Type: text/html; charset=utf-8');
|
header('Content-Type: text/html; charset=utf-8');
|
||||||
print $e->getMessage() . "\n";
|
print $e->getMessage() . "\n";
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
* @author Mike Cochrane <mikec@mikenz.geek.nz>
|
||||||
* @author Robin Millette <robin@millette.info>
|
* @author Robin Millette <robin@millette.info>
|
||||||
* @author Zach Copley <zach@status.net>
|
* @author Zach Copley <zach@status.net>
|
||||||
* @copyright 2009 StatusNet, Inc.
|
* @copyright 2009-2010 StatusNet, Inc.
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
* @link http://status.net/
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
@ -79,7 +79,6 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
|||||||
{
|
{
|
||||||
parent::prepare($args);
|
parent::prepare($args);
|
||||||
|
|
||||||
$this->user = $this->auth_user;
|
|
||||||
$this->status = $this->trimmed('status');
|
$this->status = $this->trimmed('status');
|
||||||
$this->source = $this->trimmed('source');
|
$this->source = $this->trimmed('source');
|
||||||
$this->lat = $this->trimmed('lat');
|
$this->lat = $this->trimmed('lat');
|
||||||
@ -145,7 +144,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($this->user)) {
|
if (empty($this->auth_user)) {
|
||||||
$this->clientError(_('No such user.'), 404, $this->format);
|
$this->clientError(_('No such user.'), 404, $this->format);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -172,7 +171,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
|||||||
// Check for commands
|
// Check for commands
|
||||||
|
|
||||||
$inter = new CommandInterpreter();
|
$inter = new CommandInterpreter();
|
||||||
$cmd = $inter->handle_command($this->user, $status_shortened);
|
$cmd = $inter->handle_command($this->auth_user, $status_shortened);
|
||||||
|
|
||||||
if ($cmd) {
|
if ($cmd) {
|
||||||
|
|
||||||
@ -184,7 +183,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
|||||||
// And, it returns your last status whether the cmd was successful
|
// And, it returns your last status whether the cmd was successful
|
||||||
// or not!
|
// or not!
|
||||||
|
|
||||||
$this->notice = $this->user->getCurrentNotice();
|
$this->notice = $this->auth_user->getCurrentNotice();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -211,7 +210,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
|||||||
$upload = null;
|
$upload = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$upload = MediaFile::fromUpload('media', $this->user);
|
$upload = MediaFile::fromUpload('media', $this->auth_user);
|
||||||
} catch (ClientException $ce) {
|
} catch (ClientException $ce) {
|
||||||
$this->clientError($ce->getMessage());
|
$this->clientError($ce->getMessage());
|
||||||
return;
|
return;
|
||||||
@ -234,19 +233,19 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
|||||||
|
|
||||||
$options = array('reply_to' => $reply_to);
|
$options = array('reply_to' => $reply_to);
|
||||||
|
|
||||||
if ($this->user->shareLocation()) {
|
if ($this->auth_user->shareLocation()) {
|
||||||
|
|
||||||
$locOptions = Notice::locationOptions($this->lat,
|
$locOptions = Notice::locationOptions($this->lat,
|
||||||
$this->lon,
|
$this->lon,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
$this->user->getProfile());
|
$this->auth_user->getProfile());
|
||||||
|
|
||||||
$options = array_merge($options, $locOptions);
|
$options = array_merge($options, $locOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->notice =
|
$this->notice =
|
||||||
Notice::saveNew($this->user->id,
|
Notice::saveNew($this->auth_user->id,
|
||||||
$content,
|
$content,
|
||||||
$this->source,
|
$this->source,
|
||||||
$options);
|
$options);
|
||||||
@ -255,7 +254,6 @@ class ApiStatusesUpdateAction extends ApiAuthAction
|
|||||||
$upload->attachToNotice($this->notice);
|
$upload->attachToNotice($this->notice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->showNotice();
|
$this->showNotice();
|
||||||
|
@ -138,5 +138,20 @@ class ApiStatusnetConfigAction extends ApiAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,5 +98,20 @@ class ApiStatusnetVersionAction extends ApiPrivateAuthAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,4 +123,19 @@ class ApiUserShowAction extends ApiPrivateAuthAction
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if read only.
|
||||||
|
*
|
||||||
|
* MAY override
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -416,8 +416,8 @@ class AvatarsettingsAction extends AccountSettingsAction
|
|||||||
parent::showScripts();
|
parent::showScripts();
|
||||||
|
|
||||||
if ($this->mode == 'crop') {
|
if ($this->mode == 'crop') {
|
||||||
$this->script('js/jcrop/jquery.Jcrop.min.js');
|
$this->script('jcrop/jquery.Jcrop.min.js');
|
||||||
$this->script('js/jcrop/jquery.Jcrop.go.js');
|
$this->script('jcrop/jquery.Jcrop.go.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->autofocus('avatarfile');
|
$this->autofocus('avatarfile');
|
||||||
|
@ -302,8 +302,8 @@ class DesignadminpanelAction extends AdminPanelAction
|
|||||||
{
|
{
|
||||||
parent::showScripts();
|
parent::showScripts();
|
||||||
|
|
||||||
$this->script('js/farbtastic/farbtastic.js');
|
$this->script('farbtastic/farbtastic.js');
|
||||||
$this->script('js/userdesign.go.js');
|
$this->script('userdesign.go.js');
|
||||||
|
|
||||||
$this->autofocus('design_background-image_file');
|
$this->autofocus('design_background-image_file');
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ class EditApplicationAction extends OwnerDesignAction
|
|||||||
|
|
||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
return _('Edit application');
|
return _('Edit Application');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -437,8 +437,8 @@ class GrouplogoAction extends GroupDesignAction
|
|||||||
parent::showScripts();
|
parent::showScripts();
|
||||||
|
|
||||||
if ($this->mode == 'crop') {
|
if ($this->mode == 'crop') {
|
||||||
$this->script('js/jcrop/jquery.Jcrop.min.js');
|
$this->script('jcrop/jquery.Jcrop.min.js');
|
||||||
$this->script('js/jcrop/jquery.Jcrop.go.js');
|
$this->script('jcrop/jquery.Jcrop.go.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->autofocus('avatarfile');
|
$this->autofocus('avatarfile');
|
||||||
|
@ -56,10 +56,10 @@ class InboxAction extends MailboxAction
|
|||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
if ($this->page > 1) {
|
if ($this->page > 1) {
|
||||||
return sprintf(_("Inbox for %1$s - page %2$d"), $this->user->nickname,
|
return sprintf(_('Inbox for %1$s - page %2$d'), $this->user->nickname,
|
||||||
$this->page);
|
$this->page);
|
||||||
} else {
|
} else {
|
||||||
return sprintf(_("Inbox for %s"), $this->user->nickname);
|
return sprintf(_('Inbox for %s'), $this->user->nickname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ class NewApplicationAction extends OwnerDesignAction
|
|||||||
|
|
||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
return _('New application');
|
return _('New Application');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,10 +55,10 @@ class OutboxAction extends MailboxAction
|
|||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
if ($this->page > 1) {
|
if ($this->page > 1) {
|
||||||
return sprintf(_("Outbox for %1$s - page %2$d"),
|
return sprintf(_('Outbox for %1$s - page %2$d'),
|
||||||
$this->user->nickname, $page);
|
$this->user->nickname, $page);
|
||||||
} else {
|
} else {
|
||||||
return sprintf(_("Outbox for %s"), $this->user->nickname);
|
return sprintf(_('Outbox for %s'), $this->user->nickname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
* @author Evan Prodromou <evan@status.net>
|
* @author Evan Prodromou <evan@status.net>
|
||||||
* @author Zach Copley <zach@status.net>
|
* @author Zach Copley <zach@status.net>
|
||||||
* @author Sarven Capadisli <csarven@status.net>
|
* @author Sarven Capadisli <csarven@status.net>
|
||||||
* @copyright 2008-2009 StatusNet, Inc.
|
* @copyright 2008-2010 StatusNet, Inc.
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
* @link http://status.net/
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
@ -98,6 +98,11 @@ class PathsadminpanelAction extends AdminPanelAction
|
|||||||
'background' => array('server', 'dir', 'path')
|
'background' => array('server', 'dir', 'path')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// XXX: If we're only going to have one boolean on thi page we
|
||||||
|
// can remove some of the boolean processing code --Z
|
||||||
|
|
||||||
|
static $booleans = array('site' => array('fancy'));
|
||||||
|
|
||||||
$values = array();
|
$values = array();
|
||||||
|
|
||||||
foreach ($settings as $section => $parts) {
|
foreach ($settings as $section => $parts) {
|
||||||
@ -106,6 +111,12 @@ class PathsadminpanelAction extends AdminPanelAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($booleans as $section => $parts) {
|
||||||
|
foreach ($parts as $setting) {
|
||||||
|
$values[$section][$setting] = ($this->boolean($setting)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->validate($values);
|
$this->validate($values);
|
||||||
|
|
||||||
// assert(all values are valid);
|
// assert(all values are valid);
|
||||||
@ -120,7 +131,13 @@ class PathsadminpanelAction extends AdminPanelAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$config->query('COMMIT');
|
foreach ($booleans as $section => $parts) {
|
||||||
|
foreach ($parts as $setting) {
|
||||||
|
Config::save($section, $setting, $values[$section][$setting]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$config->query('COMMIT');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -213,10 +230,14 @@ class PathsAdminPanelForm extends AdminForm
|
|||||||
|
|
||||||
function formData()
|
function formData()
|
||||||
{
|
{
|
||||||
$this->out->elementStart('fieldset', array('id' => 'settings_paths_locale'));
|
$this->out->elementStart('fieldset', array('id' => 'settings_paths_locale'));
|
||||||
$this->out->element('legend', null, _('Site'), 'site');
|
$this->out->element('legend', null, _('Site'), 'site');
|
||||||
$this->out->elementStart('ul', 'form_data');
|
$this->out->elementStart('ul', 'form_data');
|
||||||
|
|
||||||
|
$this->li();
|
||||||
|
$this->input('server', _('Server'), _('Site\'s server hostname.'));
|
||||||
|
$this->unli();
|
||||||
|
|
||||||
$this->li();
|
$this->li();
|
||||||
$this->input('path', _('Path'), _('Site path'));
|
$this->input('path', _('Path'), _('Site path'));
|
||||||
$this->unli();
|
$this->unli();
|
||||||
@ -225,6 +246,12 @@ class PathsAdminPanelForm extends AdminForm
|
|||||||
$this->input('locale_path', _('Path to locales'), _('Directory path to locales'), 'site');
|
$this->input('locale_path', _('Path to locales'), _('Directory path to locales'), 'site');
|
||||||
$this->unli();
|
$this->unli();
|
||||||
|
|
||||||
|
$this->li();
|
||||||
|
$this->out->checkbox('fancy', _('Fancy URLs'),
|
||||||
|
(bool) $this->value('fancy'),
|
||||||
|
_('Use fancy (more readable and memorable) URLs?'));
|
||||||
|
$this->unli();
|
||||||
|
|
||||||
$this->out->elementEnd('ul');
|
$this->out->elementEnd('ul');
|
||||||
$this->out->elementEnd('fieldset');
|
$this->out->elementEnd('fieldset');
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ class RepliesAction extends OwnerDesignAction
|
|||||||
if ($this->page == 1) {
|
if ($this->page == 1) {
|
||||||
return sprintf(_("Replies to %s"), $this->user->nickname);
|
return sprintf(_("Replies to %s"), $this->user->nickname);
|
||||||
} else {
|
} else {
|
||||||
return sprintf(_("Replies to %1$s, page %2$d"),
|
return sprintf(_('Replies to %1$s, page %2$d'),
|
||||||
$this->user->nickname,
|
$this->user->nickname,
|
||||||
$this->page);
|
$this->page);
|
||||||
}
|
}
|
||||||
|
@ -74,9 +74,9 @@ class ShowfavoritesAction extends OwnerDesignAction
|
|||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
if ($this->page == 1) {
|
if ($this->page == 1) {
|
||||||
return sprintf(_("%s's favorite notices"), $this->user->nickname);
|
return sprintf(_('%s\'s favorite notices'), $this->user->nickname);
|
||||||
} else {
|
} else {
|
||||||
return sprintf(_("%1$s's favorite notices, page %2$d"),
|
return sprintf(_('%1$s\'s favorite notices, page %2$d'),
|
||||||
$this->user->nickname,
|
$this->user->nickname,
|
||||||
$this->page);
|
$this->page);
|
||||||
}
|
}
|
||||||
|
@ -79,9 +79,9 @@ class ShowgroupAction extends GroupDesignAction
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->page == 1) {
|
if ($this->page == 1) {
|
||||||
return sprintf(_("%s group"), $base);
|
return sprintf(_('%s group'), $base);
|
||||||
} else {
|
} else {
|
||||||
return sprintf(_("%1$s group, page %2$d"),
|
return sprintf(_('%1$s group, page %2$d'),
|
||||||
$base,
|
$base,
|
||||||
$this->page);
|
$this->page);
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ class ShowstreamAction extends ProfileAction
|
|||||||
if ($this->page == 1) {
|
if ($this->page == 1) {
|
||||||
return $base;
|
return $base;
|
||||||
} else {
|
} else {
|
||||||
return sprintf(_("%1$s, page %2$d"),
|
return sprintf(_('%1$s, page %2$d'),
|
||||||
$base,
|
$base,
|
||||||
$this->page);
|
$this->page);
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
* @author Evan Prodromou <evan@status.net>
|
* @author Evan Prodromou <evan@status.net>
|
||||||
* @author Zach Copley <zach@status.net>
|
* @author Zach Copley <zach@status.net>
|
||||||
* @author Sarven Capadisli <csarven@status.net>
|
* @author Sarven Capadisli <csarven@status.net>
|
||||||
* @copyright 2008-2009 StatusNet, Inc.
|
* @copyright 2008-2010 StatusNet, Inc.
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
* @link http://status.net/
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
@ -95,8 +95,6 @@ class SiteadminpanelAction extends AdminPanelAction
|
|||||||
'site', 'textlimit', 'dupelimit'),
|
'site', 'textlimit', 'dupelimit'),
|
||||||
'snapshot' => array('run', 'reporturl', 'frequency'));
|
'snapshot' => array('run', 'reporturl', 'frequency'));
|
||||||
|
|
||||||
static $booleans = array('site' => array('private', 'inviteonly', 'closed', 'fancy'));
|
|
||||||
|
|
||||||
$values = array();
|
$values = array();
|
||||||
|
|
||||||
foreach ($settings as $section => $parts) {
|
foreach ($settings as $section => $parts) {
|
||||||
@ -105,12 +103,6 @@ class SiteadminpanelAction extends AdminPanelAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($booleans as $section => $parts) {
|
|
||||||
foreach ($parts as $setting) {
|
|
||||||
$values[$section][$setting] = ($this->boolean($setting)) ? 1 : 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This throws an exception on validation errors
|
// This throws an exception on validation errors
|
||||||
|
|
||||||
$this->validate($values);
|
$this->validate($values);
|
||||||
@ -127,12 +119,6 @@ class SiteadminpanelAction extends AdminPanelAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($booleans as $section => $parts) {
|
|
||||||
foreach ($parts as $setting) {
|
|
||||||
Config::save($section, $setting, $values[$section][$setting]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$config->query('COMMIT');
|
$config->query('COMMIT');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -299,44 +285,6 @@ class SiteAdminPanelForm extends AdminForm
|
|||||||
$this->out->elementEnd('ul');
|
$this->out->elementEnd('ul');
|
||||||
$this->out->elementEnd('fieldset');
|
$this->out->elementEnd('fieldset');
|
||||||
|
|
||||||
$this->out->elementStart('fieldset', array('id' => 'settings_admin_urls'));
|
|
||||||
$this->out->element('legend', null, _('URLs'));
|
|
||||||
$this->out->elementStart('ul', 'form_data');
|
|
||||||
$this->li();
|
|
||||||
$this->input('server', _('Server'), _('Site\'s server hostname.'));
|
|
||||||
$this->unli();
|
|
||||||
|
|
||||||
$this->li();
|
|
||||||
$this->out->checkbox('fancy', _('Fancy URLs'),
|
|
||||||
(bool) $this->value('fancy'),
|
|
||||||
_('Use fancy (more readable and memorable) URLs?'));
|
|
||||||
$this->unli();
|
|
||||||
$this->out->elementEnd('ul');
|
|
||||||
$this->out->elementEnd('fieldset');
|
|
||||||
|
|
||||||
$this->out->elementStart('fieldset', array('id' => 'settings_admin_access'));
|
|
||||||
$this->out->element('legend', null, _('Access'));
|
|
||||||
$this->out->elementStart('ul', 'form_data');
|
|
||||||
$this->li();
|
|
||||||
$this->out->checkbox('private', _('Private'),
|
|
||||||
(bool) $this->value('private'),
|
|
||||||
_('Prohibit anonymous users (not logged in) from viewing site?'));
|
|
||||||
$this->unli();
|
|
||||||
|
|
||||||
$this->li();
|
|
||||||
$this->out->checkbox('inviteonly', _('Invite only'),
|
|
||||||
(bool) $this->value('inviteonly'),
|
|
||||||
_('Make registration invitation only.'));
|
|
||||||
$this->unli();
|
|
||||||
|
|
||||||
$this->li();
|
|
||||||
$this->out->checkbox('closed', _('Closed'),
|
|
||||||
(bool) $this->value('closed'),
|
|
||||||
_('Disable new registrations.'));
|
|
||||||
$this->unli();
|
|
||||||
$this->out->elementEnd('ul');
|
|
||||||
$this->out->elementEnd('fieldset');
|
|
||||||
|
|
||||||
$this->out->elementStart('fieldset', array('id' => 'settings_admin_snapshots'));
|
$this->out->elementStart('fieldset', array('id' => 'settings_admin_snapshots'));
|
||||||
$this->out->element('legend', null, _('Snapshots'));
|
$this->out->element('legend', null, _('Snapshots'));
|
||||||
$this->out->elementStart('ul', 'form_data');
|
$this->out->elementStart('ul', 'form_data');
|
||||||
|
@ -63,9 +63,9 @@ class TagAction extends Action
|
|||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
if ($this->page == 1) {
|
if ($this->page == 1) {
|
||||||
return sprintf(_("Notices tagged with %s"), $this->tag);
|
return sprintf(_('Notices tagged with %s'), $this->tag);
|
||||||
} else {
|
} else {
|
||||||
return sprintf(_("Notices tagged with %1$s, page %2$d"),
|
return sprintf(_('Notices tagged with %1$s, page %2$d'),
|
||||||
$this->tag,
|
$this->tag,
|
||||||
$this->page);
|
$this->page);
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ class TagAction extends Action
|
|||||||
array('tag' => $this->tag)),
|
array('tag' => $this->tag)),
|
||||||
sprintf(_('Notice feed for tag %s (RSS 1.0)'),
|
sprintf(_('Notice feed for tag %s (RSS 1.0)'),
|
||||||
$this->tag)),
|
$this->tag)),
|
||||||
new Feed(Feed::RSS2,
|
new Feed(Feed::RSS2,
|
||||||
common_local_url('ApiTimelineTag',
|
common_local_url('ApiTimelineTag',
|
||||||
array('format' => 'rss',
|
array('format' => 'rss',
|
||||||
'tag' => $this->tag)),
|
'tag' => $this->tag)),
|
||||||
|
@ -59,9 +59,9 @@ class UsergroupsAction extends OwnerDesignAction
|
|||||||
function title()
|
function title()
|
||||||
{
|
{
|
||||||
if ($this->page == 1) {
|
if ($this->page == 1) {
|
||||||
return sprintf(_("%s groups"), $this->user->nickname);
|
return sprintf(_('%s groups'), $this->user->nickname);
|
||||||
} else {
|
} else {
|
||||||
return sprintf(_("%1$s groups, page %2$d"),
|
return sprintf(_('%1$s groups, page %2$d'),
|
||||||
$this->user->nickname,
|
$this->user->nickname,
|
||||||
$this->page);
|
$this->page);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,6 @@ class Memcached_DataObject extends DB_DataObject
|
|||||||
// Clear this out so we don't accidentally break global
|
// Clear this out so we don't accidentally break global
|
||||||
// state in *this* process.
|
// state in *this* process.
|
||||||
$this->_DB_resultid = null;
|
$this->_DB_resultid = null;
|
||||||
|
|
||||||
// We don't have any local DBO refs, so clear these out.
|
// We don't have any local DBO refs, so clear these out.
|
||||||
$this->_link_loaded = false;
|
$this->_link_loaded = false;
|
||||||
}
|
}
|
||||||
@ -91,9 +90,7 @@ class Memcached_DataObject extends DB_DataObject
|
|||||||
unset($i);
|
unset($i);
|
||||||
}
|
}
|
||||||
$i = Memcached_DataObject::getcached($cls, $k, $v);
|
$i = Memcached_DataObject::getcached($cls, $k, $v);
|
||||||
if ($i) {
|
if ($i === false) { // false == cache miss
|
||||||
return $i;
|
|
||||||
} else {
|
|
||||||
$i = DB_DataObject::factory($cls);
|
$i = DB_DataObject::factory($cls);
|
||||||
if (empty($i)) {
|
if (empty($i)) {
|
||||||
$i = false;
|
$i = false;
|
||||||
@ -101,22 +98,34 @@ class Memcached_DataObject extends DB_DataObject
|
|||||||
}
|
}
|
||||||
$result = $i->get($k, $v);
|
$result = $i->get($k, $v);
|
||||||
if ($result) {
|
if ($result) {
|
||||||
|
// Hit!
|
||||||
$i->encache();
|
$i->encache();
|
||||||
return $i;
|
|
||||||
} else {
|
} else {
|
||||||
|
// save the fact that no such row exists
|
||||||
|
$c = self::memcache();
|
||||||
|
if (!empty($c)) {
|
||||||
|
$ck = self::cachekey($cls, $k, $v);
|
||||||
|
$c->set($ck, null);
|
||||||
|
}
|
||||||
$i = false;
|
$i = false;
|
||||||
return $i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return $i;
|
||||||
}
|
}
|
||||||
|
|
||||||
function &pkeyGet($cls, $kv)
|
/**
|
||||||
|
* @fixme Should this return false on lookup fail to match staticGet?
|
||||||
|
*/
|
||||||
|
function pkeyGet($cls, $kv)
|
||||||
{
|
{
|
||||||
$i = Memcached_DataObject::multicache($cls, $kv);
|
$i = Memcached_DataObject::multicache($cls, $kv);
|
||||||
if ($i) {
|
if ($i !== false) { // false == cache miss
|
||||||
return $i;
|
return $i;
|
||||||
} else {
|
} else {
|
||||||
$i = new $cls();
|
$i = DB_DataObject::factory($cls);
|
||||||
|
if (empty($i)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
foreach ($kv as $k => $v) {
|
foreach ($kv as $k => $v) {
|
||||||
$i->$k = $v;
|
$i->$k = $v;
|
||||||
}
|
}
|
||||||
@ -124,6 +133,11 @@ class Memcached_DataObject extends DB_DataObject
|
|||||||
$i->encache();
|
$i->encache();
|
||||||
} else {
|
} else {
|
||||||
$i = null;
|
$i = null;
|
||||||
|
$c = self::memcache();
|
||||||
|
if (!empty($c)) {
|
||||||
|
$ck = self::multicacheKey($cls, $kv);
|
||||||
|
$c->set($ck, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $i;
|
return $i;
|
||||||
}
|
}
|
||||||
@ -132,6 +146,9 @@ class Memcached_DataObject extends DB_DataObject
|
|||||||
function insert()
|
function insert()
|
||||||
{
|
{
|
||||||
$result = parent::insert();
|
$result = parent::insert();
|
||||||
|
if ($result) {
|
||||||
|
$this->encache(); // in case of cached negative lookups
|
||||||
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,6 +203,17 @@ class Memcached_DataObject extends DB_DataObject
|
|||||||
|
|
||||||
function keyTypes()
|
function keyTypes()
|
||||||
{
|
{
|
||||||
|
// ini-based classes return number-indexed arrays. handbuilt
|
||||||
|
// classes return column => keytype. Make this uniform.
|
||||||
|
|
||||||
|
$keys = $this->keys();
|
||||||
|
|
||||||
|
$keyskeys = array_keys($keys);
|
||||||
|
|
||||||
|
if (is_string($keyskeys[0])) {
|
||||||
|
return $keys;
|
||||||
|
}
|
||||||
|
|
||||||
global $_DB_DATAOBJECT;
|
global $_DB_DATAOBJECT;
|
||||||
if (!isset($_DB_DATAOBJECT['INI'][$this->_database][$this->__table."__keys"])) {
|
if (!isset($_DB_DATAOBJECT['INI'][$this->_database][$this->__table."__keys"])) {
|
||||||
$this->databaseStructure();
|
$this->databaseStructure();
|
||||||
@ -197,6 +225,7 @@ class Memcached_DataObject extends DB_DataObject
|
|||||||
function encache()
|
function encache()
|
||||||
{
|
{
|
||||||
$c = $this->memcache();
|
$c = $this->memcache();
|
||||||
|
|
||||||
if (!$c) {
|
if (!$c) {
|
||||||
return false;
|
return false;
|
||||||
} else if ($this->tableName() == 'user' && is_object($this->id)) {
|
} else if ($this->tableName() == 'user' && is_object($this->id)) {
|
||||||
@ -206,64 +235,86 @@ class Memcached_DataObject extends DB_DataObject
|
|||||||
str_replace("\n", " ", $e->getTraceAsString()));
|
str_replace("\n", " ", $e->getTraceAsString()));
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
$pkey = array();
|
$keys = $this->_allCacheKeys();
|
||||||
$pval = array();
|
|
||||||
$types = $this->keyTypes();
|
foreach ($keys as $key) {
|
||||||
ksort($types);
|
$c->set($key, $this);
|
||||||
foreach ($types as $key => $type) {
|
}
|
||||||
if ($type == 'K') {
|
|
||||||
$pkey[] = $key;
|
|
||||||
$pval[] = $this->$key;
|
|
||||||
} else {
|
|
||||||
$c->set($this->cacheKey($this->tableName(), $key, $this->$key), $this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# XXX: should work for both compound and scalar pkeys
|
|
||||||
$pvals = implode(',', $pval);
|
|
||||||
$pkeys = implode(',', $pkey);
|
|
||||||
$c->set($this->cacheKey($this->tableName(), $pkeys, $pvals), $this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function decache()
|
function decache()
|
||||||
{
|
{
|
||||||
$c = $this->memcache();
|
$c = $this->memcache();
|
||||||
|
|
||||||
if (!$c) {
|
if (!$c) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
$pkey = array();
|
|
||||||
$pval = array();
|
|
||||||
$types = $this->keyTypes();
|
|
||||||
ksort($types);
|
|
||||||
foreach ($types as $key => $type) {
|
|
||||||
if ($type == 'K') {
|
|
||||||
$pkey[] = $key;
|
|
||||||
$pval[] = $this->$key;
|
|
||||||
} else {
|
|
||||||
$c->delete($this->cacheKey($this->tableName(), $key, $this->$key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# should work for both compound and scalar pkeys
|
|
||||||
# XXX: comma works for now but may not be safe separator for future keys
|
|
||||||
$pvals = implode(',', $pval);
|
|
||||||
$pkeys = implode(',', $pkey);
|
|
||||||
$c->delete($this->cacheKey($this->tableName(), $pkeys, $pvals));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$keys = $this->_allCacheKeys();
|
||||||
|
|
||||||
|
foreach ($keys as $key) {
|
||||||
|
$c->delete($key, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _allCacheKeys()
|
||||||
|
{
|
||||||
|
$ckeys = array();
|
||||||
|
|
||||||
|
$types = $this->keyTypes();
|
||||||
|
ksort($types);
|
||||||
|
|
||||||
|
$pkey = array();
|
||||||
|
$pval = array();
|
||||||
|
|
||||||
|
foreach ($types as $key => $type) {
|
||||||
|
|
||||||
|
assert(!empty($key));
|
||||||
|
|
||||||
|
if ($type == 'U') {
|
||||||
|
if (empty($this->$key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$ckeys[] = $this->cacheKey($this->tableName(), $key, $this->$key);
|
||||||
|
} else if ($type == 'K' || $type == 'N') {
|
||||||
|
$pkey[] = $key;
|
||||||
|
$pval[] = $this->$key;
|
||||||
|
} else {
|
||||||
|
throw new Exception("Unknown key type $key => $type for " . $this->tableName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(count($pkey) > 0);
|
||||||
|
|
||||||
|
// XXX: should work for both compound and scalar pkeys
|
||||||
|
$pvals = implode(',', $pval);
|
||||||
|
$pkeys = implode(',', $pkey);
|
||||||
|
|
||||||
|
$ckeys[] = $this->cacheKey($this->tableName(), $pkeys, $pvals);
|
||||||
|
|
||||||
|
return $ckeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
function multicache($cls, $kv)
|
function multicache($cls, $kv)
|
||||||
{
|
{
|
||||||
ksort($kv);
|
ksort($kv);
|
||||||
$c = Memcached_DataObject::memcache();
|
$c = self::memcache();
|
||||||
if (!$c) {
|
if (!$c) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
$pkeys = implode(',', array_keys($kv));
|
return $c->get(self::multicacheKey($cls, $kv));
|
||||||
$pvals = implode(',', array_values($kv));
|
|
||||||
return $c->get(Memcached_DataObject::cacheKey($cls, $pkeys, $pvals));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function multicacheKey($cls, $kv)
|
||||||
|
{
|
||||||
|
ksort($kv);
|
||||||
|
$pkeys = implode(',', array_keys($kv));
|
||||||
|
$pvals = implode(',', array_values($kv));
|
||||||
|
return self::cacheKey($cls, $pkeys, $pvals);
|
||||||
|
}
|
||||||
|
|
||||||
function getSearchEngine($table)
|
function getSearchEngine($table)
|
||||||
{
|
{
|
||||||
require_once INSTALLDIR.'/lib/search_engines.php';
|
require_once INSTALLDIR.'/lib/search_engines.php';
|
||||||
@ -298,7 +349,8 @@ class Memcached_DataObject extends DB_DataObject
|
|||||||
$key_part = common_keyize($cls).':'.md5($qry);
|
$key_part = common_keyize($cls).':'.md5($qry);
|
||||||
$ckey = common_cache_key($key_part);
|
$ckey = common_cache_key($key_part);
|
||||||
$stored = $c->get($ckey);
|
$stored = $c->get($ckey);
|
||||||
if ($stored) {
|
|
||||||
|
if ($stored !== false) {
|
||||||
return new ArrayWrapper($stored);
|
return new ArrayWrapper($stored);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +39,19 @@ class Status_network extends DB_DataObject
|
|||||||
public $logo; // varchar(255)
|
public $logo; // varchar(255)
|
||||||
public $created; // datetime() not_null
|
public $created; // datetime() not_null
|
||||||
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
|
||||||
|
public $tags; // text
|
||||||
|
|
||||||
/* Static get */
|
/* Static get */
|
||||||
function staticGet($k,$v=NULL) { return DB_DataObject::staticGet('Status_network',$k,$v); }
|
function staticGet($k,$v=NULL) {
|
||||||
|
$i = DB_DataObject::staticGet('Status_network',$k,$v);
|
||||||
|
|
||||||
|
// Don't use local process cache; if we're fetching multiple
|
||||||
|
// times it's because we're reloading it in a long-running
|
||||||
|
// process; we need a fresh copy!
|
||||||
|
global $_DB_DATAOBJECT;
|
||||||
|
unset($_DB_DATAOBJECT['CACHE']['status_network']);
|
||||||
|
return $i;
|
||||||
|
}
|
||||||
|
|
||||||
/* the code above is auto generated do not remove the tag below */
|
/* the code above is auto generated do not remove the tag below */
|
||||||
###END_AUTOCODE
|
###END_AUTOCODE
|
||||||
@ -245,4 +255,23 @@ class Status_network extends DB_DataObject
|
|||||||
return $this->nickname . '.' . self::$wildcard;
|
return $this->nickname . '.' . self::$wildcard;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return site meta-info tags as an array
|
||||||
|
* @return array of strings
|
||||||
|
*/
|
||||||
|
function getTags()
|
||||||
|
{
|
||||||
|
return array_filter(explode("|", strval($this->tags)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this site record has a particular meta-info tag attached.
|
||||||
|
* @param string $tag
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function hasTag($tag)
|
||||||
|
{
|
||||||
|
return in_array($tag, $this->getTags());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
create table queue_item_new (
|
|
||||||
id integer auto_increment primary key comment 'unique identifier',
|
|
||||||
frame blob not null comment 'data: object reference or opaque string',
|
|
||||||
transport varchar(8) not null comment 'queue for what? "email", "jabber", "sms", "irc", ...',
|
|
||||||
created datetime not null comment 'date this record was created',
|
|
||||||
claimed datetime comment 'date this item was claimed',
|
|
||||||
|
|
||||||
index queue_item_created_idx (created)
|
|
||||||
|
|
||||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
|
||||||
|
|
||||||
insert into queue_item_new (frame,transport,created,claimed)
|
|
||||||
select notice_id,transport,created,claimed from queue_item;
|
|
||||||
alter table queue_item rename to queue_item_old;
|
|
||||||
alter table queue_item_new rename to queue_item;
|
|
||||||
|
|
48
db/rc3torc4.sql
Normal file
48
db/rc3torc4.sql
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
create table queue_item_new (
|
||||||
|
id integer auto_increment primary key comment 'unique identifier',
|
||||||
|
frame blob not null comment 'data: object reference or opaque string',
|
||||||
|
transport varchar(8) not null comment 'queue for what? "email", "jabber", "sms", "irc", ...',
|
||||||
|
created datetime not null comment 'date this record was created',
|
||||||
|
claimed datetime comment 'date this item was claimed',
|
||||||
|
|
||||||
|
index queue_item_created_idx (created)
|
||||||
|
|
||||||
|
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
|
|
||||||
|
insert into queue_item_new (frame,transport,created,claimed)
|
||||||
|
select notice_id,transport,created,claimed from queue_item;
|
||||||
|
alter table queue_item rename to queue_item_old;
|
||||||
|
alter table queue_item_new rename to queue_item;
|
||||||
|
|
||||||
|
alter table consumer
|
||||||
|
add consumer_secret varchar(255) not null comment 'secret value',
|
||||||
|
add verifier varchar(255) comment 'verifier string for OAuth 1.0a',
|
||||||
|
add verified_callback varchar(255) comment 'verified callback URL for OAuth 1.0a';
|
||||||
|
|
||||||
|
create table oauth_application (
|
||||||
|
id integer auto_increment primary key comment 'unique identifier',
|
||||||
|
owner integer not null comment 'owner of the application' references profile (id),
|
||||||
|
consumer_key varchar(255) not null comment 'application consumer key' references consumer (consumer_key),
|
||||||
|
name varchar(255) not null comment 'name of the application',
|
||||||
|
description varchar(255) comment 'description of the application',
|
||||||
|
icon varchar(255) not null comment 'application icon',
|
||||||
|
source_url varchar(255) comment 'application homepage - used for source link',
|
||||||
|
organization varchar(255) comment 'name of the organization running the application',
|
||||||
|
homepage varchar(255) comment 'homepage for the organization',
|
||||||
|
callback_url varchar(255) comment 'url to redirect to after authentication',
|
||||||
|
type tinyint default 0 comment 'type of app, 1 = browser, 2 = desktop',
|
||||||
|
access_type tinyint default 0 comment 'default access type, bit 1 = read, bit 2 = write',
|
||||||
|
created datetime not null comment 'date this record was created',
|
||||||
|
modified timestamp comment 'date this record was modified'
|
||||||
|
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
|
|
||||||
|
create table oauth_application_user (
|
||||||
|
profile_id integer not null comment 'user of the application' references profile (id),
|
||||||
|
application_id integer not null comment 'id of the application' references oauth_application (id),
|
||||||
|
access_type tinyint default 0 comment 'access type, bit 1 = read, bit 2 = write, bit 3 = revoked',
|
||||||
|
token varchar(255) comment 'request or access token',
|
||||||
|
created datetime not null comment 'date this record was created',
|
||||||
|
modified timestamp comment 'date this record was modified',
|
||||||
|
constraint primary key (profile_id, application_id)
|
||||||
|
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
|
|
@ -14,6 +14,8 @@ create table status_network (
|
|||||||
sitename varchar(255) comment 'display name',
|
sitename varchar(255) comment 'display name',
|
||||||
theme varchar(255) comment 'theme name',
|
theme varchar(255) comment 'theme name',
|
||||||
logo varchar(255) comment 'site logo',
|
logo varchar(255) comment 'site logo',
|
||||||
|
|
||||||
|
tags text comment 'site meta-info tags (pipe-separated)',
|
||||||
|
|
||||||
created datetime not null comment 'date this record was created',
|
created datetime not null comment 'date this record was created',
|
||||||
modified timestamp comment 'date this record was modified'
|
modified timestamp comment 'date this record was modified'
|
||||||
|
@ -246,18 +246,18 @@ class Action extends HTMLOutputter // lawsuit
|
|||||||
{
|
{
|
||||||
if (Event::handle('StartShowScripts', array($this))) {
|
if (Event::handle('StartShowScripts', array($this))) {
|
||||||
if (Event::handle('StartShowJQueryScripts', array($this))) {
|
if (Event::handle('StartShowJQueryScripts', array($this))) {
|
||||||
$this->script('js/jquery.min.js');
|
$this->script('jquery.min.js');
|
||||||
$this->script('js/jquery.form.js');
|
$this->script('jquery.form.js');
|
||||||
$this->script('js/jquery.cookie.js');
|
$this->script('jquery.cookie.js');
|
||||||
$this->script('js/json2.js');
|
$this->script('json2.js');
|
||||||
$this->script('js/jquery.joverlay.min.js');
|
$this->script('jquery.joverlay.min.js');
|
||||||
Event::handle('EndShowJQueryScripts', array($this));
|
Event::handle('EndShowJQueryScripts', array($this));
|
||||||
}
|
}
|
||||||
if (Event::handle('StartShowStatusNetScripts', array($this)) &&
|
if (Event::handle('StartShowStatusNetScripts', array($this)) &&
|
||||||
Event::handle('StartShowLaconicaScripts', array($this))) {
|
Event::handle('StartShowLaconicaScripts', array($this))) {
|
||||||
$this->script('js/xbImportNode.js');
|
$this->script('xbImportNode.js');
|
||||||
$this->script('js/util.js');
|
$this->script('util.js');
|
||||||
$this->script('js/geometa.js');
|
$this->script('geometa.js');
|
||||||
// Frame-busting code to avoid clickjacking attacks.
|
// Frame-busting code to avoid clickjacking attacks.
|
||||||
$this->element('script', array('type' => 'text/javascript'),
|
$this->element('script', array('type' => 'text/javascript'),
|
||||||
'if (window.top !== window.self) { window.top.location.href = window.self.location.href; }');
|
'if (window.top !== window.self) { window.top.location.href = window.self.location.href; }');
|
||||||
@ -392,8 +392,14 @@ class Action extends HTMLOutputter // lawsuit
|
|||||||
$this->elementStart('address', array('id' => 'site_contact',
|
$this->elementStart('address', array('id' => 'site_contact',
|
||||||
'class' => 'vcard'));
|
'class' => 'vcard'));
|
||||||
if (Event::handle('StartAddressData', array($this))) {
|
if (Event::handle('StartAddressData', array($this))) {
|
||||||
|
if (common_config('singleuser', 'enabled')) {
|
||||||
|
$url = common_local_url('showstream',
|
||||||
|
array('nickname' => common_config('singleuser', 'nickname')));
|
||||||
|
} else {
|
||||||
|
$url = common_local_url('public');
|
||||||
|
}
|
||||||
$this->elementStart('a', array('class' => 'url home bookmark',
|
$this->elementStart('a', array('class' => 'url home bookmark',
|
||||||
'href' => common_local_url('public')));
|
'href' => $url));
|
||||||
if (common_config('site', 'logo') || file_exists(Theme::file('logo.png'))) {
|
if (common_config('site', 'logo') || file_exists(Theme::file('logo.png'))) {
|
||||||
$this->element('img', array('class' => 'logo photo',
|
$this->element('img', array('class' => 'logo photo',
|
||||||
'src' => (common_config('site', 'logo')) ? common_config('site', 'logo') : Theme::path('logo.png'),
|
'src' => (common_config('site', 'logo')) ? common_config('site', 'logo') : Theme::path('logo.png'),
|
||||||
|
@ -319,12 +319,17 @@ class AdminPanelNav extends Widget
|
|||||||
|
|
||||||
if ($this->canAdmin('user')) {
|
if ($this->canAdmin('user')) {
|
||||||
$this->out->menuItem(common_local_url('useradminpanel'), _('User'),
|
$this->out->menuItem(common_local_url('useradminpanel'), _('User'),
|
||||||
_('Paths configuration'), $action_name == 'useradminpanel', 'nav_design_admin_panel');
|
_('User configuration'), $action_name == 'useradminpanel', 'nav_design_admin_panel');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->canAdmin('paths')) {
|
if ($this->canAdmin('access')) {
|
||||||
$this->out->menuItem(common_local_url('pathsadminpanel'), _('Paths'),
|
$this->out->menuItem(common_local_url('accessadminpanel'), _('Access'),
|
||||||
_('Paths configuration'), $action_name == 'pathsadminpanel', 'nav_design_admin_panel');
|
_('Access configuration'), $action_name == 'accessadminpanel', 'nav_design_admin_panel');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->canAdmin('paths')) {
|
||||||
|
$this->out->menuItem(common_local_url('pathsadminpanel'), _('Paths'),
|
||||||
|
_('Paths configuration'), $action_name == 'pathsadminpanel', 'nav_design_admin_panel');
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::handle('EndAdminPanelNav', array($this));
|
Event::handle('EndAdminPanelNav', array($this));
|
||||||
|
157
lib/apiauth.php
157
lib/apiauth.php
@ -29,7 +29,7 @@
|
|||||||
* @author mEDI <medi@milaro.net>
|
* @author mEDI <medi@milaro.net>
|
||||||
* @author Sarven Capadisli <csarven@status.net>
|
* @author Sarven Capadisli <csarven@status.net>
|
||||||
* @author Zach Copley <zach@status.net>
|
* @author Zach Copley <zach@status.net>
|
||||||
* @copyright 2009 StatusNet, Inc.
|
* @copyright 2009-2010 StatusNet, Inc.
|
||||||
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
* @link http://status.net/
|
* @link http://status.net/
|
||||||
*/
|
*/
|
||||||
@ -53,9 +53,10 @@ require_once INSTALLDIR . '/lib/apioauth.php';
|
|||||||
|
|
||||||
class ApiAuthAction extends ApiAction
|
class ApiAuthAction extends ApiAction
|
||||||
{
|
{
|
||||||
var $access_token;
|
var $auth_user_nickname = null;
|
||||||
var $oauth_access_type;
|
var $auth_user_password = null;
|
||||||
var $oauth_source;
|
var $access_token = null;
|
||||||
|
var $oauth_source = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take arguments for running, and output basic auth header if needed
|
* Take arguments for running, and output basic auth header if needed
|
||||||
@ -70,22 +71,40 @@ class ApiAuthAction extends ApiAction
|
|||||||
{
|
{
|
||||||
parent::prepare($args);
|
parent::prepare($args);
|
||||||
|
|
||||||
|
$this->consumer_key = $this->arg('oauth_consumer_key');
|
||||||
|
$this->access_token = $this->arg('oauth_token');
|
||||||
|
|
||||||
|
// NOTE: $this->auth_user has to get set in prepare(), not handle(),
|
||||||
|
// because subclasses do stuff with it in their prepares.
|
||||||
|
|
||||||
if ($this->requiresAuth()) {
|
if ($this->requiresAuth()) {
|
||||||
|
|
||||||
$this->consumer_key = $this->arg('oauth_consumer_key');
|
|
||||||
$this->access_token = $this->arg('oauth_token');
|
|
||||||
|
|
||||||
if (!empty($this->access_token)) {
|
if (!empty($this->access_token)) {
|
||||||
$this->checkOAuthRequest();
|
$this->checkOAuthRequest();
|
||||||
} else {
|
} else {
|
||||||
$this->checkBasicAuthUser();
|
$this->checkBasicAuthUser(true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Check to see if a basic auth user is there even
|
// Check to see if a basic auth user is there even
|
||||||
// if one's not required
|
// if one's not required
|
||||||
|
|
||||||
$this->checkBasicAuthUser(false);
|
if (empty($this->access_token)) {
|
||||||
|
$this->checkBasicAuthUser(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reject API calls with the wrong access level
|
||||||
|
|
||||||
|
if ($this->isReadOnly($args) == false) {
|
||||||
|
|
||||||
|
common_debug(get_class($this) . ' is not read-only!');
|
||||||
|
|
||||||
|
if ($this->access != self::READ_WRITE) {
|
||||||
|
$msg = _('API resource requires read-write access, ' .
|
||||||
|
'but you only have read access.');
|
||||||
|
$this->clientError($msg, 401, $this->format);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -98,8 +117,6 @@ class ApiAuthAction extends ApiAction
|
|||||||
|
|
||||||
function checkOAuthRequest()
|
function checkOAuthRequest()
|
||||||
{
|
{
|
||||||
common_debug("We have an OAuth request.");
|
|
||||||
|
|
||||||
$datastore = new ApiStatusNetOAuthDataStore();
|
$datastore = new ApiStatusNetOAuthDataStore();
|
||||||
$server = new OAuthServer($datastore);
|
$server = new OAuthServer($datastore);
|
||||||
$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
|
$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
|
||||||
@ -117,9 +134,10 @@ class ApiAuthAction extends ApiAction
|
|||||||
|
|
||||||
if (empty($app)) {
|
if (empty($app)) {
|
||||||
|
|
||||||
// this should really not happen
|
// this should probably not happen
|
||||||
common_log(LOG_WARN,
|
common_log(LOG_WARNING,
|
||||||
"Couldn't find the OAuth app for consumer key: $this->consumer_key");
|
'Couldn\'t find the OAuth app for consumer key: ' .
|
||||||
|
$this->consumer_key);
|
||||||
|
|
||||||
throw new OAuthException('No application for that consumer key.');
|
throw new OAuthException('No application for that consumer key.');
|
||||||
}
|
}
|
||||||
@ -131,20 +149,18 @@ class ApiAuthAction extends ApiAction
|
|||||||
$appUser = Oauth_application_user::staticGet('token',
|
$appUser = Oauth_application_user::staticGet('token',
|
||||||
$this->access_token);
|
$this->access_token);
|
||||||
|
|
||||||
// XXX: check that app->id and appUser->application_id and consumer all
|
// XXX: Check that app->id and appUser->application_id and consumer all
|
||||||
// match?
|
// match?
|
||||||
|
|
||||||
if (!empty($appUser)) {
|
if (!empty($appUser)) {
|
||||||
|
|
||||||
// read or read-write
|
|
||||||
$this->oauth_access_type = $appUser->access_type;
|
|
||||||
|
|
||||||
// If access_type == 0 we have either a request token
|
// If access_type == 0 we have either a request token
|
||||||
// or a bad / revoked access token
|
// or a bad / revoked access token
|
||||||
|
|
||||||
if ($this->oauth_access_type != 0) {
|
if ($appUser->access_type != 0) {
|
||||||
|
|
||||||
|
// Set the access level for the api call
|
||||||
|
|
||||||
// Set the read or read-write access for the api call
|
|
||||||
$this->access = ($appUser->access_type & Oauth_application::$writeAccess)
|
$this->access = ($appUser->access_type & Oauth_application::$writeAccess)
|
||||||
? self::READ_WRITE : self::READ_ONLY;
|
? self::READ_WRITE : self::READ_ONLY;
|
||||||
|
|
||||||
@ -154,38 +170,34 @@ class ApiAuthAction extends ApiAction
|
|||||||
}
|
}
|
||||||
|
|
||||||
$msg = "API OAuth authentication for user '%s' (id: %d) on behalf of " .
|
$msg = "API OAuth authentication for user '%s' (id: %d) on behalf of " .
|
||||||
"application '%s' (id: %d).";
|
"application '%s' (id: %d) with %s access.";
|
||||||
|
|
||||||
common_log(LOG_INFO, sprintf($msg,
|
common_log(LOG_INFO, sprintf($msg,
|
||||||
$this->auth_user->nickname,
|
$this->auth_user->nickname,
|
||||||
$this->auth_user->id,
|
$this->auth_user->id,
|
||||||
$app->name,
|
$app->name,
|
||||||
$app->id));
|
$app->id,
|
||||||
return true;
|
($this->access = self::READ_WRITE) ?
|
||||||
|
'read-write' : 'read-only'
|
||||||
|
));
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
throw new OAuthException('Bad access token.');
|
throw new OAuthException('Bad access token.');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// also should not happen
|
// Also should not happen
|
||||||
|
|
||||||
throw new OAuthException('No user for that token.');
|
throw new OAuthException('No user for that token.');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (OAuthException $e) {
|
} catch (OAuthException $e) {
|
||||||
common_log(LOG_WARN, 'API OAuthException - ' . $e->getMessage());
|
common_log(LOG_WARNING, 'API OAuthException - ' . $e->getMessage());
|
||||||
common_debug(var_export($req, true));
|
$this->showAuthError();
|
||||||
$this->showOAuthError($e->getMessage());
|
exit;
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showOAuthError($msg)
|
|
||||||
{
|
|
||||||
header('HTTP/1.1 401 Unauthorized');
|
|
||||||
header('Content-Type: text/html; charset=utf-8');
|
|
||||||
print $msg . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does this API resource require authentication?
|
* Does this API resource require authentication?
|
||||||
*
|
*
|
||||||
@ -210,43 +222,48 @@ class ApiAuthAction extends ApiAction
|
|||||||
|
|
||||||
$realm = common_config('site', 'name') . ' API';
|
$realm = common_config('site', 'name') . ' API';
|
||||||
|
|
||||||
if (!isset($this->auth_user) && $required) {
|
if (!isset($this->auth_user_nickname) && $required) {
|
||||||
header('WWW-Authenticate: Basic realm="' . $realm . '"');
|
header('WWW-Authenticate: Basic realm="' . $realm . '"');
|
||||||
|
|
||||||
// show error if the user clicks 'cancel'
|
// show error if the user clicks 'cancel'
|
||||||
|
|
||||||
$this->showBasicAuthError();
|
$this->showAuthError();
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
} else if (isset($this->auth_user)) {
|
} else {
|
||||||
$nickname = $this->auth_user;
|
|
||||||
$password = $this->auth_pw;
|
|
||||||
$user = common_check_user($nickname, $password);
|
|
||||||
if (Event::handle('StartSetApiUser', array(&$user))) {
|
|
||||||
$this->auth_user = $user;
|
|
||||||
|
|
||||||
// By default, all basic auth users have read and write access
|
$user = common_check_user($this->auth_user_nickname,
|
||||||
$this->access = self::READ_WRITE;
|
$this->auth_user_password);
|
||||||
|
|
||||||
|
if (Event::handle('StartSetApiUser', array(&$user))) {
|
||||||
|
|
||||||
|
if (!empty($user)) {
|
||||||
|
$this->auth_user = $user;
|
||||||
|
}
|
||||||
|
|
||||||
Event::handle('EndSetApiUser', array($user));
|
Event::handle('EndSetApiUser', array($user));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($this->auth_user)) {
|
// By default, basic auth users have rw access
|
||||||
|
|
||||||
|
$this->access = self::READ_WRITE;
|
||||||
|
|
||||||
|
if (empty($this->auth_user) && $required) {
|
||||||
|
|
||||||
// basic authentication failed
|
// basic authentication failed
|
||||||
|
|
||||||
list($proxy, $ip) = common_client_ip();
|
list($proxy, $ip) = common_client_ip();
|
||||||
common_log(
|
|
||||||
LOG_WARNING,
|
$msg = sprintf(_('Failed API auth attempt, nickname = %1$s, ' .
|
||||||
'Failed API auth attempt, nickname = ' .
|
'proxy = %2$s, ip = %3$s'),
|
||||||
"$nickname, proxy = $proxy, ip = $ip."
|
$this->auth_user_nickname,
|
||||||
);
|
$proxy,
|
||||||
$this->showBasicAuthError();
|
$ip);
|
||||||
|
common_log(LOG_WARNING, $msg);
|
||||||
|
$this->showAuthError();
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -260,32 +277,30 @@ class ApiAuthAction extends ApiAction
|
|||||||
{
|
{
|
||||||
if (isset($_SERVER['AUTHORIZATION'])
|
if (isset($_SERVER['AUTHORIZATION'])
|
||||||
|| isset($_SERVER['HTTP_AUTHORIZATION'])
|
|| isset($_SERVER['HTTP_AUTHORIZATION'])
|
||||||
) {
|
) {
|
||||||
$authorization_header = isset($_SERVER['HTTP_AUTHORIZATION'])
|
$authorization_header = isset($_SERVER['HTTP_AUTHORIZATION'])
|
||||||
? $_SERVER['HTTP_AUTHORIZATION'] : $_SERVER['AUTHORIZATION'];
|
? $_SERVER['HTTP_AUTHORIZATION'] : $_SERVER['AUTHORIZATION'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_SERVER['PHP_AUTH_USER'])) {
|
if (isset($_SERVER['PHP_AUTH_USER'])) {
|
||||||
$this->auth_user = $_SERVER['PHP_AUTH_USER'];
|
$this->auth_user_nickname = $_SERVER['PHP_AUTH_USER'];
|
||||||
$this->auth_pw = $_SERVER['PHP_AUTH_PW'];
|
$this->auth_user_password = $_SERVER['PHP_AUTH_PW'];
|
||||||
} elseif (isset($authorization_header)
|
} elseif (isset($authorization_header)
|
||||||
&& strstr(substr($authorization_header, 0, 5), 'Basic')) {
|
&& strstr(substr($authorization_header, 0, 5), 'Basic')) {
|
||||||
|
|
||||||
// decode the HTTP_AUTHORIZATION header on php-cgi server self
|
// Decode the HTTP_AUTHORIZATION header on php-cgi server self
|
||||||
// on fcgid server the header name is AUTHORIZATION
|
// on fcgid server the header name is AUTHORIZATION
|
||||||
|
|
||||||
$auth_hash = base64_decode(substr($authorization_header, 6));
|
$auth_hash = base64_decode(substr($authorization_header, 6));
|
||||||
list($this->auth_user, $this->auth_pw) = explode(':', $auth_hash);
|
list($this->auth_user_nickname,
|
||||||
|
$this->auth_user_password) = explode(':', $auth_hash);
|
||||||
|
|
||||||
// set all to null on a empty basic auth request
|
// Set all to null on a empty basic auth request
|
||||||
|
|
||||||
if ($this->auth_user == "") {
|
if (empty($this->auth_user_nickname)) {
|
||||||
$this->auth_user = null;
|
$this->auth_user_nickname = null;
|
||||||
$this->auth_pw = null;
|
$this->auth_password = null;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$this->auth_user = null;
|
|
||||||
$this->auth_pw = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,7 +311,7 @@ class ApiAuthAction extends ApiAction
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function showBasicAuthError()
|
function showAuthError()
|
||||||
{
|
{
|
||||||
header('HTTP/1.1 401 Unauthorized');
|
header('HTTP/1.1 401 Unauthorized');
|
||||||
$msg = 'Could not authenticate you.';
|
$msg = 'Could not authenticate you.';
|
||||||
|
@ -56,7 +56,7 @@ $default =
|
|||||||
'dupelimit' => 60, # default for same person saying the same thing
|
'dupelimit' => 60, # default for same person saying the same thing
|
||||||
'textlimit' => 140,
|
'textlimit' => 140,
|
||||||
'indent' => true,
|
'indent' => true,
|
||||||
'use_x_sendfile' => false,
|
'use_x_sendfile' => false
|
||||||
),
|
),
|
||||||
'db' =>
|
'db' =>
|
||||||
array('database' => 'YOU HAVE TO SET THIS IN config.php',
|
array('database' => 'YOU HAVE TO SET THIS IN config.php',
|
||||||
@ -81,6 +81,7 @@ $default =
|
|||||||
'subsystem' => 'db', # default to database, or 'stomp'
|
'subsystem' => 'db', # default to database, or 'stomp'
|
||||||
'stomp_server' => null,
|
'stomp_server' => null,
|
||||||
'queue_basename' => '/queue/statusnet/',
|
'queue_basename' => '/queue/statusnet/',
|
||||||
|
'control_channel' => '/topic/statusnet-control', // broadcasts to all queue daemons
|
||||||
'stomp_username' => null,
|
'stomp_username' => null,
|
||||||
'stomp_password' => null,
|
'stomp_password' => null,
|
||||||
'monitor' => null, // URL to monitor ping endpoint (work in progress)
|
'monitor' => null, // URL to monitor ping endpoint (work in progress)
|
||||||
@ -119,6 +120,9 @@ $default =
|
|||||||
array('server' => null,
|
array('server' => null,
|
||||||
'dir' => null,
|
'dir' => null,
|
||||||
'path'=> null),
|
'path'=> null),
|
||||||
|
'javascript' =>
|
||||||
|
array('server' => null,
|
||||||
|
'path'=> null),
|
||||||
'throttle' =>
|
'throttle' =>
|
||||||
array('enabled' => false, // whether to throttle edits; false by default
|
array('enabled' => false, // whether to throttle edits; false by default
|
||||||
'count' => 20, // number of allowed messages in timespan
|
'count' => 20, // number of allowed messages in timespan
|
||||||
@ -261,5 +265,8 @@ $default =
|
|||||||
'OpenID' => null),
|
'OpenID' => null),
|
||||||
),
|
),
|
||||||
'admin' =>
|
'admin' =>
|
||||||
array('panels' => array('design', 'site', 'user', 'paths')),
|
array('panels' => array('design', 'site', 'user', 'paths', 'access')),
|
||||||
|
'singleuser' =>
|
||||||
|
array('enabled' => false,
|
||||||
|
'nickname' => null),
|
||||||
);
|
);
|
||||||
|
@ -327,8 +327,8 @@ class DesignSettingsAction extends AccountSettingsAction
|
|||||||
{
|
{
|
||||||
parent::showScripts();
|
parent::showScripts();
|
||||||
|
|
||||||
$this->script('js/farbtastic/farbtastic.js');
|
$this->script('farbtastic/farbtastic.js');
|
||||||
$this->script('js/userdesign.go.js');
|
$this->script('userdesign.go.js');
|
||||||
|
|
||||||
$this->autofocus('design_background-image_file');
|
$this->autofocus('design_background-image_file');
|
||||||
}
|
}
|
||||||
|
@ -351,14 +351,40 @@ class HTMLOutputter extends XMLOutputter
|
|||||||
function script($src, $type='text/javascript')
|
function script($src, $type='text/javascript')
|
||||||
{
|
{
|
||||||
if(Event::handle('StartScriptElement', array($this,&$src,&$type))) {
|
if(Event::handle('StartScriptElement', array($this,&$src,&$type))) {
|
||||||
|
|
||||||
$url = parse_url($src);
|
$url = parse_url($src);
|
||||||
|
|
||||||
if( empty($url['scheme']) && empty($url['host']) && empty($url['query']) && empty($url['fragment']))
|
if( empty($url['scheme']) && empty($url['host']) && empty($url['query']) && empty($url['fragment']))
|
||||||
{
|
{
|
||||||
$src = common_path($src) . '?version=' . STATUSNET_VERSION;
|
$path = common_config('javascript', 'path');
|
||||||
|
|
||||||
|
if (empty($path)) {
|
||||||
|
$path = common_config('site', 'path') . '/js/';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($path[strlen($path)-1] != '/') {
|
||||||
|
$path .= '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($path[0] != '/') {
|
||||||
|
$path = '/'.$path;
|
||||||
|
}
|
||||||
|
|
||||||
|
$server = common_config('javascript', 'server');
|
||||||
|
|
||||||
|
if (empty($server)) {
|
||||||
|
$server = common_config('site', 'server');
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: protocol
|
||||||
|
|
||||||
|
$src = 'http://'.$server.$path.$src . '?version=' . STATUSNET_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->element('script', array('type' => $type,
|
$this->element('script', array('type' => $type,
|
||||||
'src' => $src),
|
'src' => $src),
|
||||||
' ');
|
' ');
|
||||||
|
|
||||||
Event::handle('EndScriptElement', array($this,$src,$type));
|
Event::handle('EndScriptElement', array($this,$src,$type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,9 @@ abstract class IoMaster
|
|||||||
protected $pollTimeouts = array();
|
protected $pollTimeouts = array();
|
||||||
protected $lastPoll = array();
|
protected $lastPoll = array();
|
||||||
|
|
||||||
|
public $shutdown = false; // Did we do a graceful shutdown?
|
||||||
|
public $respawn = true; // Should we respawn after shutdown?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $id process ID to use in logging/monitoring
|
* @param string $id process ID to use in logging/monitoring
|
||||||
*/
|
*/
|
||||||
@ -148,7 +151,7 @@ abstract class IoMaster
|
|||||||
$this->logState('init');
|
$this->logState('init');
|
||||||
$this->start();
|
$this->start();
|
||||||
|
|
||||||
while (true) {
|
while (!$this->shutdown) {
|
||||||
$timeouts = array_values($this->pollTimeouts);
|
$timeouts = array_values($this->pollTimeouts);
|
||||||
$timeouts[] = 60; // default max timeout
|
$timeouts[] = 60; // default max timeout
|
||||||
|
|
||||||
@ -200,22 +203,31 @@ abstract class IoMaster
|
|||||||
$this->logState('idle');
|
$this->logState('idle');
|
||||||
$this->idle();
|
$this->idle();
|
||||||
|
|
||||||
$memoryLimit = $this->softMemoryLimit();
|
$this->checkMemory();
|
||||||
if ($memoryLimit > 0) {
|
|
||||||
$usage = memory_get_usage();
|
|
||||||
if ($usage > $memoryLimit) {
|
|
||||||
common_log(LOG_INFO, "Queue thread hit soft memory limit ($usage > $memoryLimit); gracefully restarting.");
|
|
||||||
break;
|
|
||||||
} else if (common_config('queue', 'debug_memory')) {
|
|
||||||
common_log(LOG_DEBUG, "Memory usage $usage");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->logState('shutdown');
|
$this->logState('shutdown');
|
||||||
$this->finish();
|
$this->finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check runtime memory usage, possibly triggering a graceful shutdown
|
||||||
|
* and thread respawn if we've crossed the soft limit.
|
||||||
|
*/
|
||||||
|
protected function checkMemory()
|
||||||
|
{
|
||||||
|
$memoryLimit = $this->softMemoryLimit();
|
||||||
|
if ($memoryLimit > 0) {
|
||||||
|
$usage = memory_get_usage();
|
||||||
|
if ($usage > $memoryLimit) {
|
||||||
|
common_log(LOG_INFO, "Queue thread hit soft memory limit ($usage > $memoryLimit); gracefully restarting.");
|
||||||
|
$this->requestRestart();
|
||||||
|
} else if (common_config('queue', 'debug_memory')) {
|
||||||
|
common_log(LOG_DEBUG, "Memory usage $usage");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return fully-parsed soft memory limit in bytes.
|
* Return fully-parsed soft memory limit in bytes.
|
||||||
* @return intval 0 or -1 if not set
|
* @return intval 0 or -1 if not set
|
||||||
@ -358,5 +370,24 @@ abstract class IoMaster
|
|||||||
$owners[] = "thread:" . $this->id;
|
$owners[] = "thread:" . $this->id;
|
||||||
$this->monitor->stats($key, $owners);
|
$this->monitor->stats($key, $owners);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For IoManagers to request a graceful shutdown at end of event loop.
|
||||||
|
*/
|
||||||
|
public function requestShutdown()
|
||||||
|
{
|
||||||
|
$this->shutdown = true;
|
||||||
|
$this->respawn = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For IoManagers to request a graceful restart at end of event loop.
|
||||||
|
*/
|
||||||
|
public function requestRestart()
|
||||||
|
{
|
||||||
|
$this->shutdown = true;
|
||||||
|
$this->respawn = true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,9 +78,9 @@ class PersonalGroupNav extends Widget
|
|||||||
function show()
|
function show()
|
||||||
{
|
{
|
||||||
$user = null;
|
$user = null;
|
||||||
|
|
||||||
// FIXME: we should probably pass this in
|
// FIXME: we should probably pass this in
|
||||||
|
|
||||||
$action = $this->action->trimmed('action');
|
$action = $this->action->trimmed('action');
|
||||||
$nickname = $this->action->trimmed('nickname');
|
$nickname = $this->action->trimmed('nickname');
|
||||||
|
|
||||||
@ -117,7 +117,8 @@ class PersonalGroupNav extends Widget
|
|||||||
|
|
||||||
$cur = common_current_user();
|
$cur = common_current_user();
|
||||||
|
|
||||||
if ($cur && $cur->id == $user->id) {
|
if ($cur && $cur->id == $user->id &&
|
||||||
|
!common_config('singleuser', 'enabled')) {
|
||||||
|
|
||||||
$this->out->menuItem(common_local_url('inbox', array('nickname' =>
|
$this->out->menuItem(common_local_url('inbox', array('nickname' =>
|
||||||
$nickname)),
|
$nickname)),
|
||||||
|
@ -100,6 +100,23 @@ abstract class QueueManager extends IoManager
|
|||||||
$this->initialize();
|
$this->initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional; ping any running queue handler daemons with a notification
|
||||||
|
* such as announcing a new site to handle or requesting clean shutdown.
|
||||||
|
* This avoids having to restart all the daemons manually to update configs
|
||||||
|
* and such.
|
||||||
|
*
|
||||||
|
* Called from scripts/queuectl.php controller utility.
|
||||||
|
*
|
||||||
|
* @param string $event event key
|
||||||
|
* @param string $param optional parameter to append to key
|
||||||
|
* @return boolean success
|
||||||
|
*/
|
||||||
|
public function sendControlSignal($event, $param='')
|
||||||
|
{
|
||||||
|
throw new Exception(get_class($this) . " does not support control signals.");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store an object (usually/always a Notice) into the given queue
|
* Store an object (usually/always a Notice) into the given queue
|
||||||
* for later processing. No guarantee is made on when it will be
|
* for later processing. No guarantee is made on when it will be
|
||||||
|
216
lib/router.php
216
lib/router.php
@ -73,12 +73,6 @@ class Router
|
|||||||
|
|
||||||
if (Event::handle('StartInitializeRouter', array(&$m))) {
|
if (Event::handle('StartInitializeRouter', array(&$m))) {
|
||||||
|
|
||||||
// In the "root"
|
|
||||||
|
|
||||||
$m->connect('', array('action' => 'public'));
|
|
||||||
$m->connect('rss', array('action' => 'publicrss'));
|
|
||||||
$m->connect('featuredrss', array('action' => 'featuredrss'));
|
|
||||||
$m->connect('favoritedrss', array('action' => 'favoritedrss'));
|
|
||||||
$m->connect('opensearch/people', array('action' => 'opensearch',
|
$m->connect('opensearch/people', array('action' => 'opensearch',
|
||||||
'type' => 'people'));
|
'type' => 'people'));
|
||||||
$m->connect('opensearch/notice', array('action' => 'opensearch',
|
$m->connect('opensearch/notice', array('action' => 'opensearch',
|
||||||
@ -145,6 +139,18 @@ class Router
|
|||||||
$m->connect('settings/'.$s, array('action' => $s.'settings'));
|
$m->connect('settings/'.$s, array('action' => $s.'settings'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$m->connect('settings/oauthapps/show/:id',
|
||||||
|
array('action' => 'showapplication'),
|
||||||
|
array('id' => '[0-9]+')
|
||||||
|
);
|
||||||
|
$m->connect('settings/oauthapps/new',
|
||||||
|
array('action' => 'newapplication')
|
||||||
|
);
|
||||||
|
$m->connect('settings/oauthapps/edit/:id',
|
||||||
|
array('action' => 'editapplication'),
|
||||||
|
array('id' => '[0-9]+')
|
||||||
|
);
|
||||||
|
|
||||||
// search
|
// search
|
||||||
|
|
||||||
foreach (array('group', 'people', 'notice') as $s) {
|
foreach (array('group', 'people', 'notice') as $s) {
|
||||||
@ -227,11 +233,6 @@ class Router
|
|||||||
array('action' => 'peopletag'),
|
array('action' => 'peopletag'),
|
||||||
array('tag' => '[a-zA-Z0-9]+'));
|
array('tag' => '[a-zA-Z0-9]+'));
|
||||||
|
|
||||||
$m->connect('featured/', array('action' => 'featured'));
|
|
||||||
$m->connect('featured', array('action' => 'featured'));
|
|
||||||
$m->connect('favorited/', array('action' => 'favorited'));
|
|
||||||
$m->connect('favorited', array('action' => 'favorited'));
|
|
||||||
|
|
||||||
// groups
|
// groups
|
||||||
|
|
||||||
$m->connect('group/new', array('action' => 'newgroup'));
|
$m->connect('group/new', array('action' => 'newgroup'));
|
||||||
@ -622,37 +623,6 @@ class Router
|
|||||||
$m->connect('api/search.json', array('action' => 'twitapisearchjson'));
|
$m->connect('api/search.json', array('action' => 'twitapisearchjson'));
|
||||||
$m->connect('api/trends.json', array('action' => 'twitapitrends'));
|
$m->connect('api/trends.json', array('action' => 'twitapitrends'));
|
||||||
|
|
||||||
$m->connect('admin/site', array('action' => 'siteadminpanel'));
|
|
||||||
$m->connect('admin/design', array('action' => 'designadminpanel'));
|
|
||||||
$m->connect('admin/user', array('action' => 'useradminpanel'));
|
|
||||||
$m->connect('admin/paths', array('action' => 'pathsadminpanel'));
|
|
||||||
|
|
||||||
$m->connect('getfile/:filename',
|
|
||||||
array('action' => 'getfile'),
|
|
||||||
array('filename' => '[A-Za-z0-9._-]+'));
|
|
||||||
|
|
||||||
// user stuff
|
|
||||||
|
|
||||||
foreach (array('subscriptions', 'subscribers',
|
|
||||||
'nudge', 'all', 'foaf', 'xrds',
|
|
||||||
'replies', 'inbox', 'outbox', 'microsummary') as $a) {
|
|
||||||
$m->connect(':nickname/'.$a,
|
|
||||||
array('action' => $a),
|
|
||||||
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$m->connect('settings/oauthapps/show/:id',
|
|
||||||
array('action' => 'showapplication'),
|
|
||||||
array('id' => '[0-9]+')
|
|
||||||
);
|
|
||||||
$m->connect('settings/oauthapps/new',
|
|
||||||
array('action' => 'newapplication')
|
|
||||||
);
|
|
||||||
$m->connect('settings/oauthapps/edit/:id',
|
|
||||||
array('action' => 'editapplication'),
|
|
||||||
array('id' => '[0-9]+')
|
|
||||||
);
|
|
||||||
|
|
||||||
$m->connect('api/oauth/request_token',
|
$m->connect('api/oauth/request_token',
|
||||||
array('action' => 'apioauthrequesttoken'));
|
array('action' => 'apioauthrequesttoken'));
|
||||||
|
|
||||||
@ -662,47 +632,137 @@ class Router
|
|||||||
$m->connect('api/oauth/authorize',
|
$m->connect('api/oauth/authorize',
|
||||||
array('action' => 'apioauthauthorize'));
|
array('action' => 'apioauthauthorize'));
|
||||||
|
|
||||||
foreach (array('subscriptions', 'subscribers') as $a) {
|
// Admin
|
||||||
$m->connect(':nickname/'.$a.'/:tag',
|
|
||||||
array('action' => $a),
|
$m->connect('admin/site', array('action' => 'siteadminpanel'));
|
||||||
array('tag' => '[a-zA-Z0-9]+',
|
$m->connect('admin/design', array('action' => 'designadminpanel'));
|
||||||
|
$m->connect('admin/user', array('action' => 'useradminpanel'));
|
||||||
|
$m->connect('admin/access', array('action' => 'accessadminpanel'));
|
||||||
|
$m->connect('admin/paths', array('action' => 'pathsadminpanel'));
|
||||||
|
|
||||||
|
$m->connect('getfile/:filename',
|
||||||
|
array('action' => 'getfile'),
|
||||||
|
array('filename' => '[A-Za-z0-9._-]+'));
|
||||||
|
|
||||||
|
// In the "root"
|
||||||
|
|
||||||
|
if (common_config('singleuser', 'enabled')) {
|
||||||
|
|
||||||
|
$nickname = common_config('singleuser', 'nickname');
|
||||||
|
|
||||||
|
foreach (array('subscriptions', 'subscribers',
|
||||||
|
'all', 'foaf', 'xrds',
|
||||||
|
'replies', 'microsummary') as $a) {
|
||||||
|
$m->connect($a,
|
||||||
|
array('action' => $a,
|
||||||
|
'nickname' => $nickname));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array('subscriptions', 'subscribers') as $a) {
|
||||||
|
$m->connect($a.'/:tag',
|
||||||
|
array('action' => $a,
|
||||||
|
'nickname' => $nickname),
|
||||||
|
array('tag' => '[a-zA-Z0-9]+'));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array('rss', 'groups') as $a) {
|
||||||
|
$m->connect($a,
|
||||||
|
array('action' => 'user'.$a,
|
||||||
|
'nickname' => $nickname));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array('all', 'replies', 'favorites') as $a) {
|
||||||
|
$m->connect($a.'/rss',
|
||||||
|
array('action' => $a.'rss',
|
||||||
|
'nickname' => $nickname));
|
||||||
|
}
|
||||||
|
|
||||||
|
$m->connect('favorites',
|
||||||
|
array('action' => 'showfavorites',
|
||||||
|
'nickname' => $nickname));
|
||||||
|
|
||||||
|
$m->connect('avatar/:size',
|
||||||
|
array('action' => 'avatarbynickname',
|
||||||
|
'nickname' => $nickname),
|
||||||
|
array('size' => '(original|96|48|24)'));
|
||||||
|
|
||||||
|
$m->connect('tag/:tag/rss',
|
||||||
|
array('action' => 'userrss',
|
||||||
|
'nickname' => $nickname),
|
||||||
|
array('tag' => '[a-zA-Z0-9]+'));
|
||||||
|
|
||||||
|
$m->connect('tag/:tag',
|
||||||
|
array('action' => 'showstream',
|
||||||
|
'nickname' => $nickname),
|
||||||
|
array('tag' => '[a-zA-Z0-9]+'));
|
||||||
|
|
||||||
|
$m->connect('',
|
||||||
|
array('action' => 'showstream',
|
||||||
|
'nickname' => $nickname));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$m->connect('', array('action' => 'public'));
|
||||||
|
$m->connect('rss', array('action' => 'publicrss'));
|
||||||
|
$m->connect('featuredrss', array('action' => 'featuredrss'));
|
||||||
|
$m->connect('favoritedrss', array('action' => 'favoritedrss'));
|
||||||
|
$m->connect('featured/', array('action' => 'featured'));
|
||||||
|
$m->connect('featured', array('action' => 'featured'));
|
||||||
|
$m->connect('favorited/', array('action' => 'favorited'));
|
||||||
|
$m->connect('favorited', array('action' => 'favorited'));
|
||||||
|
|
||||||
|
foreach (array('subscriptions', 'subscribers',
|
||||||
|
'nudge', 'all', 'foaf', 'xrds',
|
||||||
|
'replies', 'inbox', 'outbox', 'microsummary') as $a) {
|
||||||
|
$m->connect(':nickname/'.$a,
|
||||||
|
array('action' => $a),
|
||||||
|
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array('subscriptions', 'subscribers') as $a) {
|
||||||
|
$m->connect(':nickname/'.$a.'/:tag',
|
||||||
|
array('action' => $a),
|
||||||
|
array('tag' => '[a-zA-Z0-9]+',
|
||||||
|
'nickname' => '[a-zA-Z0-9]{1,64}'));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array('rss', 'groups') as $a) {
|
||||||
|
$m->connect(':nickname/'.$a,
|
||||||
|
array('action' => 'user'.$a),
|
||||||
|
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array('all', 'replies', 'favorites') as $a) {
|
||||||
|
$m->connect(':nickname/'.$a.'/rss',
|
||||||
|
array('action' => $a.'rss'),
|
||||||
|
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$m->connect(':nickname/favorites',
|
||||||
|
array('action' => 'showfavorites'),
|
||||||
|
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
||||||
|
|
||||||
|
$m->connect(':nickname/avatar/:size',
|
||||||
|
array('action' => 'avatarbynickname'),
|
||||||
|
array('size' => '(original|96|48|24)',
|
||||||
'nickname' => '[a-zA-Z0-9]{1,64}'));
|
'nickname' => '[a-zA-Z0-9]{1,64}'));
|
||||||
}
|
|
||||||
|
|
||||||
foreach (array('rss', 'groups') as $a) {
|
$m->connect(':nickname/tag/:tag/rss',
|
||||||
$m->connect(':nickname/'.$a,
|
array('action' => 'userrss'),
|
||||||
array('action' => 'user'.$a),
|
array('nickname' => '[a-zA-Z0-9]{1,64}'),
|
||||||
|
array('tag' => '[a-zA-Z0-9]+'));
|
||||||
|
|
||||||
|
$m->connect(':nickname/tag/:tag',
|
||||||
|
array('action' => 'showstream'),
|
||||||
|
array('nickname' => '[a-zA-Z0-9]{1,64}'),
|
||||||
|
array('tag' => '[a-zA-Z0-9]+'));
|
||||||
|
|
||||||
|
$m->connect(':nickname',
|
||||||
|
array('action' => 'showstream'),
|
||||||
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (array('all', 'replies', 'favorites') as $a) {
|
// user stuff
|
||||||
$m->connect(':nickname/'.$a.'/rss',
|
|
||||||
array('action' => $a.'rss'),
|
|
||||||
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$m->connect(':nickname/favorites',
|
|
||||||
array('action' => 'showfavorites'),
|
|
||||||
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
|
||||||
|
|
||||||
$m->connect(':nickname/avatar/:size',
|
|
||||||
array('action' => 'avatarbynickname'),
|
|
||||||
array('size' => '(original|96|48|24)',
|
|
||||||
'nickname' => '[a-zA-Z0-9]{1,64}'));
|
|
||||||
|
|
||||||
$m->connect(':nickname/tag/:tag/rss',
|
|
||||||
array('action' => 'userrss'),
|
|
||||||
array('nickname' => '[a-zA-Z0-9]{1,64}'),
|
|
||||||
array('tag' => '[a-zA-Z0-9]+'));
|
|
||||||
|
|
||||||
$m->connect(':nickname/tag/:tag',
|
|
||||||
array('action' => 'showstream'),
|
|
||||||
array('nickname' => '[a-zA-Z0-9]{1,64}'),
|
|
||||||
array('tag' => '[a-zA-Z0-9]+'));
|
|
||||||
|
|
||||||
$m->connect(':nickname',
|
|
||||||
array('action' => 'showstream'),
|
|
||||||
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
|
||||||
|
|
||||||
Event::handle('RouterInitialized', array($m));
|
Event::handle('RouterInitialized', array($m));
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,11 @@ abstract class SpawningDaemon extends Daemon
|
|||||||
{
|
{
|
||||||
protected $threads=1;
|
protected $threads=1;
|
||||||
|
|
||||||
|
const EXIT_OK = 0;
|
||||||
|
const EXIT_ERR = 1;
|
||||||
|
const EXIT_SHUTDOWN = 100;
|
||||||
|
const EXIT_RESTART = 101;
|
||||||
|
|
||||||
function __construct($id=null, $daemonize=true, $threads=1)
|
function __construct($id=null, $daemonize=true, $threads=1)
|
||||||
{
|
{
|
||||||
parent::__construct($daemonize);
|
parent::__construct($daemonize);
|
||||||
@ -49,7 +54,7 @@ abstract class SpawningDaemon extends Daemon
|
|||||||
/**
|
/**
|
||||||
* Perform some actual work!
|
* Perform some actual work!
|
||||||
*
|
*
|
||||||
* @return boolean true on success, false on failure
|
* @return int exit code; use self::EXIT_SHUTDOWN to request not to respawn.
|
||||||
*/
|
*/
|
||||||
public abstract function runThread();
|
public abstract function runThread();
|
||||||
|
|
||||||
@ -84,23 +89,30 @@ abstract class SpawningDaemon extends Daemon
|
|||||||
while (count($children) > 0) {
|
while (count($children) > 0) {
|
||||||
$status = null;
|
$status = null;
|
||||||
$pid = pcntl_wait($status);
|
$pid = pcntl_wait($status);
|
||||||
if ($pid > 0) {
|
if ($pid > 0 && pcntl_wifexited($status)) {
|
||||||
|
$exitCode = pcntl_wexitstatus($status);
|
||||||
|
|
||||||
$i = array_search($pid, $children);
|
$i = array_search($pid, $children);
|
||||||
if ($i === false) {
|
if ($i === false) {
|
||||||
$this->log(LOG_ERR, "Unrecognized child pid $pid exited!");
|
$this->log(LOG_ERR, "Unrecognized child pid $pid exited with status $exitCode");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
unset($children[$i]);
|
unset($children[$i]);
|
||||||
$this->log(LOG_INFO, "Thread $i pid $pid exited.");
|
|
||||||
|
if ($this->shouldRespawn($exitCode)) {
|
||||||
$pid = pcntl_fork();
|
$this->log(LOG_INFO, "Thread $i pid $pid exited with status $exitCode; respawing.");
|
||||||
if ($pid < 0) {
|
|
||||||
$this->log(LOG_ERROR, "Couldn't fork to respawn thread $i; aborting thread.\n");
|
$pid = pcntl_fork();
|
||||||
} else if ($pid == 0) {
|
if ($pid < 0) {
|
||||||
$this->initAndRunChild($i);
|
$this->log(LOG_ERROR, "Couldn't fork to respawn thread $i; aborting thread.\n");
|
||||||
|
} else if ($pid == 0) {
|
||||||
|
$this->initAndRunChild($i);
|
||||||
|
} else {
|
||||||
|
$this->log(LOG_INFO, "Respawned thread $i as pid $pid");
|
||||||
|
$children[$i] = $pid;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->log(LOG_INFO, "Respawned thread $i as pid $pid");
|
$this->log(LOG_INFO, "Thread $i pid $pid exited with status $exitCode; closing out thread.");
|
||||||
$children[$i] = $pid;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,6 +120,24 @@ abstract class SpawningDaemon extends Daemon
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether to respawn an exited subprocess based on its exit code.
|
||||||
|
* Otherwise we'll respawn all exits by default.
|
||||||
|
*
|
||||||
|
* @param int $exitCode
|
||||||
|
* @return boolean true to respawn
|
||||||
|
*/
|
||||||
|
protected function shouldRespawn($exitCode)
|
||||||
|
{
|
||||||
|
if ($exitCode == self::EXIT_SHUTDOWN) {
|
||||||
|
// Thread requested a clean shutdown.
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// Otherwise we should always respawn!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize things for a fresh thread, call runThread(), and
|
* Initialize things for a fresh thread, call runThread(), and
|
||||||
* exit at completion with appropriate return value.
|
* exit at completion with appropriate return value.
|
||||||
@ -116,8 +146,8 @@ abstract class SpawningDaemon extends Daemon
|
|||||||
{
|
{
|
||||||
$this->set_id($this->get_id() . "." . $thread);
|
$this->set_id($this->get_id() . "." . $thread);
|
||||||
$this->resetDb();
|
$this->resetDb();
|
||||||
$ok = $this->runThread();
|
$exitCode = $this->runThread();
|
||||||
exit($ok ? 0 : 1);
|
exit($exitCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,8 +38,10 @@ class StompQueueManager extends QueueManager
|
|||||||
var $password = null;
|
var $password = null;
|
||||||
var $base = null;
|
var $base = null;
|
||||||
var $con = null;
|
var $con = null;
|
||||||
|
protected $control;
|
||||||
|
|
||||||
protected $sites = array();
|
protected $sites = array();
|
||||||
|
protected $subscriptions = array();
|
||||||
|
|
||||||
protected $useTransactions = true;
|
protected $useTransactions = true;
|
||||||
protected $transaction = null;
|
protected $transaction = null;
|
||||||
@ -52,6 +54,7 @@ class StompQueueManager extends QueueManager
|
|||||||
$this->username = common_config('queue', 'stomp_username');
|
$this->username = common_config('queue', 'stomp_username');
|
||||||
$this->password = common_config('queue', 'stomp_password');
|
$this->password = common_config('queue', 'stomp_password');
|
||||||
$this->base = common_config('queue', 'queue_basename');
|
$this->base = common_config('queue', 'queue_basename');
|
||||||
|
$this->control = common_config('queue', 'control_channel');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,6 +80,36 @@ class StompQueueManager extends QueueManager
|
|||||||
$this->initialize();
|
$this->initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional; ping any running queue handler daemons with a notification
|
||||||
|
* such as announcing a new site to handle or requesting clean shutdown.
|
||||||
|
* This avoids having to restart all the daemons manually to update configs
|
||||||
|
* and such.
|
||||||
|
*
|
||||||
|
* Currently only relevant for multi-site queue managers such as Stomp.
|
||||||
|
*
|
||||||
|
* @param string $event event key
|
||||||
|
* @param string $param optional parameter to append to key
|
||||||
|
* @return boolean success
|
||||||
|
*/
|
||||||
|
public function sendControlSignal($event, $param='')
|
||||||
|
{
|
||||||
|
$message = $event;
|
||||||
|
if ($param != '') {
|
||||||
|
$message .= ':' . $param;
|
||||||
|
}
|
||||||
|
$this->_connect();
|
||||||
|
$result = $this->con->send($this->control,
|
||||||
|
$message,
|
||||||
|
array ('created' => common_sql_now()));
|
||||||
|
if ($result) {
|
||||||
|
$this->_log(LOG_INFO, "Sent control ping to queue daemons: $message");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
$this->_log(LOG_ERR, "Failed sending control ping to queue daemons: $message");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate the appropriate QueueHandler class for the given queue.
|
* Instantiate the appropriate QueueHandler class for the given queue.
|
||||||
@ -86,7 +119,7 @@ class StompQueueManager extends QueueManager
|
|||||||
*/
|
*/
|
||||||
function getHandler($queue)
|
function getHandler($queue)
|
||||||
{
|
{
|
||||||
$handlers = $this->handlers[common_config('site', 'server')];
|
$handlers = $this->handlers[$this->currentSite()];
|
||||||
if (isset($handlers[$queue])) {
|
if (isset($handlers[$queue])) {
|
||||||
$class = $handlers[$queue];
|
$class = $handlers[$queue];
|
||||||
if (class_exists($class)) {
|
if (class_exists($class)) {
|
||||||
@ -108,7 +141,7 @@ class StompQueueManager extends QueueManager
|
|||||||
function getQueues()
|
function getQueues()
|
||||||
{
|
{
|
||||||
$group = $this->activeGroup();
|
$group = $this->activeGroup();
|
||||||
$site = common_config('site', 'server');
|
$site = $this->currentSite();
|
||||||
if (empty($this->groups[$site][$group])) {
|
if (empty($this->groups[$site][$group])) {
|
||||||
return array();
|
return array();
|
||||||
} else {
|
} else {
|
||||||
@ -126,8 +159,8 @@ class StompQueueManager extends QueueManager
|
|||||||
*/
|
*/
|
||||||
public function connect($transport, $class, $group='queuedaemon')
|
public function connect($transport, $class, $group='queuedaemon')
|
||||||
{
|
{
|
||||||
$this->handlers[common_config('site', 'server')][$transport] = $class;
|
$this->handlers[$this->currentSite()][$transport] = $class;
|
||||||
$this->groups[common_config('site', 'server')][$group][$transport] = $class;
|
$this->groups[$this->currentSite()][$group][$transport] = $class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,7 +178,8 @@ class StompQueueManager extends QueueManager
|
|||||||
|
|
||||||
$result = $this->con->send($this->queueName($queue),
|
$result = $this->con->send($this->queueName($queue),
|
||||||
$msg, // BODY of the message
|
$msg, // BODY of the message
|
||||||
array ('created' => common_sql_now()));
|
array ('created' => common_sql_now(),
|
||||||
|
'persistent' => 'true'));
|
||||||
|
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
common_log(LOG_ERR, "Error sending $rep to $queue queue");
|
common_log(LOG_ERR, "Error sending $rep to $queue queue");
|
||||||
@ -180,7 +214,16 @@ class StompQueueManager extends QueueManager
|
|||||||
$ok = true;
|
$ok = true;
|
||||||
$frames = $this->con->readFrames();
|
$frames = $this->con->readFrames();
|
||||||
foreach ($frames as $frame) {
|
foreach ($frames as $frame) {
|
||||||
$ok = $ok && $this->_handleItem($frame);
|
$dest = $frame->headers['destination'];
|
||||||
|
if ($dest == $this->control) {
|
||||||
|
if (!$this->handleControlSignal($frame)) {
|
||||||
|
// We got a control event that requests a shutdown;
|
||||||
|
// close out and stop handling anything else!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$ok = $ok && $this->handleItem($frame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $ok;
|
return $ok;
|
||||||
}
|
}
|
||||||
@ -197,6 +240,9 @@ class StompQueueManager extends QueueManager
|
|||||||
public function start($master)
|
public function start($master)
|
||||||
{
|
{
|
||||||
parent::start($master);
|
parent::start($master);
|
||||||
|
$this->_connect();
|
||||||
|
|
||||||
|
$this->con->subscribe($this->control);
|
||||||
if ($this->sites) {
|
if ($this->sites) {
|
||||||
foreach ($this->sites as $server) {
|
foreach ($this->sites as $server) {
|
||||||
StatusNet::init($server);
|
StatusNet::init($server);
|
||||||
@ -221,6 +267,7 @@ class StompQueueManager extends QueueManager
|
|||||||
// If there are any outstanding delivered messages we haven't processed,
|
// If there are any outstanding delivered messages we haven't processed,
|
||||||
// free them for another thread to take.
|
// free them for another thread to take.
|
||||||
$this->rollback();
|
$this->rollback();
|
||||||
|
$this->con->unsubscribe($this->control);
|
||||||
if ($this->sites) {
|
if ($this->sites) {
|
||||||
foreach ($this->sites as $server) {
|
foreach ($this->sites as $server) {
|
||||||
StatusNet::init($server);
|
StatusNet::init($server);
|
||||||
@ -231,7 +278,16 @@ class StompQueueManager extends QueueManager
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get identifier of the currently active site configuration
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function currentSite()
|
||||||
|
{
|
||||||
|
return common_config('site', 'server'); // @fixme switch to nickname
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lazy open connection to Stomp queue server.
|
* Lazy open connection to Stomp queue server.
|
||||||
*/
|
*/
|
||||||
@ -255,22 +311,29 @@ class StompQueueManager extends QueueManager
|
|||||||
*/
|
*/
|
||||||
protected function doSubscribe()
|
protected function doSubscribe()
|
||||||
{
|
{
|
||||||
|
$site = $this->currentSite();
|
||||||
$this->_connect();
|
$this->_connect();
|
||||||
foreach ($this->getQueues() as $queue) {
|
foreach ($this->getQueues() as $queue) {
|
||||||
$rawqueue = $this->queueName($queue);
|
$rawqueue = $this->queueName($queue);
|
||||||
|
$this->subscriptions[$site][$queue] = $rawqueue;
|
||||||
$this->_log(LOG_INFO, "Subscribing to $rawqueue");
|
$this->_log(LOG_INFO, "Subscribing to $rawqueue");
|
||||||
$this->con->subscribe($rawqueue);
|
$this->con->subscribe($rawqueue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribe from all enabled notice queues for the current site.
|
* Subscribe from all enabled notice queues for the current site.
|
||||||
*/
|
*/
|
||||||
protected function doUnsubscribe()
|
protected function doUnsubscribe()
|
||||||
{
|
{
|
||||||
|
$site = $this->currentSite();
|
||||||
$this->_connect();
|
$this->_connect();
|
||||||
foreach ($this->getQueues() as $queue) {
|
if (!empty($this->subscriptions[$site])) {
|
||||||
$this->con->unsubscribe($this->queueName($queue));
|
foreach ($this->subscriptions[$site] as $queue => $rawqueue) {
|
||||||
|
$this->_log(LOG_INFO, "Unsubscribing from $rawqueue");
|
||||||
|
$this->con->unsubscribe($rawqueue);
|
||||||
|
unset($this->subscriptions[$site][$queue]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,10 +349,10 @@ class StompQueueManager extends QueueManager
|
|||||||
* @param StompFrame $frame
|
* @param StompFrame $frame
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected function _handleItem($frame)
|
protected function handleItem($frame)
|
||||||
{
|
{
|
||||||
list($site, $queue) = $this->parseDestination($frame->headers['destination']);
|
list($site, $queue) = $this->parseDestination($frame->headers['destination']);
|
||||||
if ($site != common_config('site', 'server')) {
|
if ($site != $this->currentSite()) {
|
||||||
$this->stats('switch');
|
$this->stats('switch');
|
||||||
StatusNet::init($site);
|
StatusNet::init($site);
|
||||||
}
|
}
|
||||||
@ -317,7 +380,7 @@ class StompQueueManager extends QueueManager
|
|||||||
|
|
||||||
$handler = $this->getHandler($queue);
|
$handler = $this->getHandler($queue);
|
||||||
if (!$handler) {
|
if (!$handler) {
|
||||||
$this->_log(LOG_ERROR, "Missing handler class; skipping $info");
|
$this->_log(LOG_ERR, "Missing handler class; skipping $info");
|
||||||
$this->ack($frame);
|
$this->ack($frame);
|
||||||
$this->commit();
|
$this->commit();
|
||||||
$this->begin();
|
$this->begin();
|
||||||
@ -348,6 +411,77 @@ class StompQueueManager extends QueueManager
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a control signal broadcast.
|
||||||
|
*
|
||||||
|
* @param array $frame Stomp frame
|
||||||
|
* @return bool true to continue; false to stop further processing.
|
||||||
|
*/
|
||||||
|
protected function handleControlSignal($frame)
|
||||||
|
{
|
||||||
|
$message = trim($frame->body);
|
||||||
|
if (strpos($message, ':') !== false) {
|
||||||
|
list($event, $param) = explode(':', $message, 2);
|
||||||
|
} else {
|
||||||
|
$event = $message;
|
||||||
|
$param = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$shutdown = false;
|
||||||
|
|
||||||
|
if ($event == 'shutdown') {
|
||||||
|
$this->master->requestShutdown();
|
||||||
|
$shutdown = true;
|
||||||
|
} else if ($event == 'restart') {
|
||||||
|
$this->master->requestRestart();
|
||||||
|
$shutdown = true;
|
||||||
|
} else if ($event == 'update') {
|
||||||
|
$this->updateSiteConfig($param);
|
||||||
|
} else {
|
||||||
|
$this->_log(LOG_ERR, "Ignoring unrecognized control message: $message");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->ack($frame);
|
||||||
|
$this->commit();
|
||||||
|
$this->begin();
|
||||||
|
return $shutdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set us up with queue subscriptions for a new site added at runtime,
|
||||||
|
* triggered by a broadcast to the 'statusnet-control' topic.
|
||||||
|
*
|
||||||
|
* @param array $frame Stomp frame
|
||||||
|
* @return bool true to continue; false to stop further processing.
|
||||||
|
*/
|
||||||
|
protected function updateSiteConfig($nickname)
|
||||||
|
{
|
||||||
|
if (empty($this->sites)) {
|
||||||
|
if ($nickname == common_config('site', 'nickname')) {
|
||||||
|
StatusNet::init(common_config('site', 'server'));
|
||||||
|
$this->doUnsubscribe();
|
||||||
|
$this->doSubscribe();
|
||||||
|
} else {
|
||||||
|
$this->_log(LOG_INFO, "Ignoring update ping for other site $nickname");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$sn = Status_network::staticGet($nickname);
|
||||||
|
if ($sn) {
|
||||||
|
$server = $sn->getServerName(); // @fixme do config-by-nick
|
||||||
|
StatusNet::init($server);
|
||||||
|
if (empty($this->sites[$server])) {
|
||||||
|
$this->addSite($server);
|
||||||
|
}
|
||||||
|
$this->_log(LOG_INFO, "(Re)subscribing to queues for site $nickname / $server");
|
||||||
|
$this->doUnsubscribe();
|
||||||
|
$this->doSubscribe();
|
||||||
|
$this->stats('siteupdate');
|
||||||
|
} else {
|
||||||
|
$this->_log(LOG_ERR, "Ignoring ping for unrecognized new site $nickname");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combines the queue_basename from configuration with the
|
* Combines the queue_basename from configuration with the
|
||||||
* site server name and queue name to give eg:
|
* site server name and queue name to give eg:
|
||||||
@ -360,7 +494,7 @@ class StompQueueManager extends QueueManager
|
|||||||
protected function queueName($queue)
|
protected function queueName($queue)
|
||||||
{
|
{
|
||||||
return common_config('queue', 'queue_basename') .
|
return common_config('queue', 'queue_basename') .
|
||||||
common_config('site', 'server') . '/' . $queue;
|
$this->currentSite() . '/' . $queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
204
lib/uapplugin.php
Normal file
204
lib/uapplugin.php
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* UAP (Universal Ad Package) plugin
|
||||||
|
*
|
||||||
|
* 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 Sarven Capadisli <csarven@status.net>
|
||||||
|
* @author Evan Prodromou <evan@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') && !defined('LACONICA')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract superclass for advertising plugins
|
||||||
|
*
|
||||||
|
* Plugins for showing ads should derive from this plugin.
|
||||||
|
*
|
||||||
|
* Outputs the following ad types (based on UAP):
|
||||||
|
*
|
||||||
|
* Medium Rectangle 300x250
|
||||||
|
* Rectangle 180x150
|
||||||
|
* Leaderboard 728x90
|
||||||
|
* Wide Skyscraper 160x600
|
||||||
|
*
|
||||||
|
* @category Plugin
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Sarven Capadisli <csarven@status.net>
|
||||||
|
* @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/
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class UAPPlugin extends Plugin
|
||||||
|
{
|
||||||
|
public $mediumRectangle = null;
|
||||||
|
public $rectangle = null;
|
||||||
|
public $leaderboard = null;
|
||||||
|
public $wideSkyscraper = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output our dedicated stylesheet
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return boolean hook flag
|
||||||
|
*/
|
||||||
|
|
||||||
|
function onEndShowStatusNetStyles($action)
|
||||||
|
{
|
||||||
|
// XXX: allow override by theme
|
||||||
|
$action->cssLink('css/uap.css', 'base', 'screen, projection, tv');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a medium rectangle ad at the beginning of sidebar
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return boolean hook flag
|
||||||
|
*/
|
||||||
|
|
||||||
|
function onStartShowAside($action)
|
||||||
|
{
|
||||||
|
if (!is_null($this->mediumRectangle)) {
|
||||||
|
|
||||||
|
$action->elementStart('div',
|
||||||
|
array('id' => 'ad_medium-rectangle',
|
||||||
|
'class' => 'ad'));
|
||||||
|
|
||||||
|
$this->showMediumRectangle($action);
|
||||||
|
|
||||||
|
$action->elementEnd('div');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a leaderboard in the header
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return boolean hook flag
|
||||||
|
*/
|
||||||
|
|
||||||
|
function onEndShowHeader($action)
|
||||||
|
{
|
||||||
|
if (!is_null($this->leaderboard)) {
|
||||||
|
$action->elementStart('div',
|
||||||
|
array('id' => 'ad_leaderboard',
|
||||||
|
'class' => 'ad'));
|
||||||
|
$this->showLeaderboard($action);
|
||||||
|
$action->elementEnd('div');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a rectangle before aside sections
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return boolean hook flag
|
||||||
|
*/
|
||||||
|
|
||||||
|
function onStartShowSections($action)
|
||||||
|
{
|
||||||
|
if (!is_null($this->rectangle)) {
|
||||||
|
$action->elementStart('div',
|
||||||
|
array('id' => 'ad_rectangle',
|
||||||
|
'class' => 'ad'));
|
||||||
|
$this->showRectangle($action);
|
||||||
|
$action->elementEnd('div');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a wide skyscraper after the aside
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return boolean hook flag
|
||||||
|
*/
|
||||||
|
|
||||||
|
function onEndShowAside($action)
|
||||||
|
{
|
||||||
|
if (!is_null($this->wideSkyscraper)) {
|
||||||
|
$action->elementStart('div',
|
||||||
|
array('id' => 'ad_wide-skyscraper',
|
||||||
|
'class' => 'ad'));
|
||||||
|
|
||||||
|
$this->showWideSkyscraper($action);
|
||||||
|
|
||||||
|
$action->elementEnd('div');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a medium rectangle ad
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract protected function showMediumRectangle($action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a rectangle ad
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract protected function showRectangle($action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a wide skyscraper ad
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract protected function showWideSkyscraper($action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a leaderboard ad
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract protected function showLeaderboard($action);
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
124
plugins/BlankAd/BlankAdPlugin.php
Normal file
124
plugins/BlankAd/BlankAdPlugin.php
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Plugin for testing ad layout
|
||||||
|
*
|
||||||
|
* 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 Ads
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin for testing ad layout
|
||||||
|
*
|
||||||
|
* This plugin uses the UAPPlugin framework to output ad content. However,
|
||||||
|
* its ad content is just images with one red pixel stretched to the
|
||||||
|
* right size. It's mostly useful for debugging theme layout.
|
||||||
|
*
|
||||||
|
* To use this plugin, set the parameter for the ad size you want to use
|
||||||
|
* to true (or anything non-null). For example, to make a leaderboard:
|
||||||
|
*
|
||||||
|
* addPlugin('BlankAd', array('leaderboard' => true));
|
||||||
|
*
|
||||||
|
* @category Plugin
|
||||||
|
* @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/
|
||||||
|
*
|
||||||
|
* @seeAlso Location
|
||||||
|
*/
|
||||||
|
|
||||||
|
class BlankAdPlugin extends UAPPlugin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Show a medium rectangle 'ad'
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected function showMediumRectangle($action)
|
||||||
|
{
|
||||||
|
$action->element('img',
|
||||||
|
array('width' => 300,
|
||||||
|
'height' => 250,
|
||||||
|
'src' => common_path('plugins/BlankAd/redpixel.png')),
|
||||||
|
'');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a rectangle 'ad'
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected function showRectangle($action)
|
||||||
|
{
|
||||||
|
$action->element('img',
|
||||||
|
array('width' => 180,
|
||||||
|
'height' => 150,
|
||||||
|
'src' => common_path('plugins/BlankAd/redpixel.png')),
|
||||||
|
'');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a wide skyscraper ad
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected function showWideSkyscraper($action)
|
||||||
|
{
|
||||||
|
$action->element('img',
|
||||||
|
array('width' => 160,
|
||||||
|
'height' => 600,
|
||||||
|
'src' => common_path('plugins/BlankAd/redpixel.png')),
|
||||||
|
'');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a leaderboard ad
|
||||||
|
*
|
||||||
|
* @param Action $action Action being shown
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected function showLeaderboard($action)
|
||||||
|
{
|
||||||
|
$action->element('img',
|
||||||
|
array('width' => 728,
|
||||||
|
'height' => 90,
|
||||||
|
'src' => common_path('plugins/BlankAd/redpixel.png')),
|
||||||
|
'');
|
||||||
|
}
|
||||||
|
}
|
BIN
plugins/BlankAd/redpixel.png
Normal file
BIN
plugins/BlankAd/redpixel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 159 B |
@ -89,7 +89,7 @@ class FacebookAction extends Action
|
|||||||
|
|
||||||
function showScripts()
|
function showScripts()
|
||||||
{
|
{
|
||||||
$this->script('js/facebookapp.js');
|
$this->script('facebookapp.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,6 +79,21 @@ class PubSubHubBubPlugin extends Plugin
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if plugin should be active; may be mass-enabled.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
|
||||||
|
function enabled()
|
||||||
|
{
|
||||||
|
if (common_config('site', 'private')) {
|
||||||
|
// PuSH relies on public feeds
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// @fixme check for being on a private network?
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hooks the StartApiAtom event
|
* Hooks the StartApiAtom event
|
||||||
*
|
*
|
||||||
@ -92,8 +107,9 @@ class PubSubHubBubPlugin extends Plugin
|
|||||||
|
|
||||||
function onStartApiAtom($action)
|
function onStartApiAtom($action)
|
||||||
{
|
{
|
||||||
$action->element('link', array('rel' => 'hub', 'href' => $this->hub), null);
|
if ($this->enabled()) {
|
||||||
|
$action->element('link', array('rel' => 'hub', 'href' => $this->hub), null);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,9 +126,11 @@ class PubSubHubBubPlugin extends Plugin
|
|||||||
|
|
||||||
function onStartApiRss($action)
|
function onStartApiRss($action)
|
||||||
{
|
{
|
||||||
$action->element('atom:link', array('rel' => 'hub',
|
if ($this->enabled()) {
|
||||||
'href' => $this->hub),
|
$action->element('atom:link', array('rel' => 'hub',
|
||||||
null);
|
'href' => $this->hub),
|
||||||
|
null);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +148,9 @@ class PubSubHubBubPlugin extends Plugin
|
|||||||
|
|
||||||
function onHandleQueuedNotice($notice)
|
function onHandleQueuedNotice($notice)
|
||||||
{
|
{
|
||||||
|
if (!$this->enabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$publisher = new Publisher($this->hub);
|
$publisher = new Publisher($this->hub);
|
||||||
|
|
||||||
$feeds = array();
|
$feeds = array();
|
||||||
@ -243,16 +264,21 @@ class PubSubHubBubPlugin extends Plugin
|
|||||||
|
|
||||||
function onPluginVersion(&$versions)
|
function onPluginVersion(&$versions)
|
||||||
{
|
{
|
||||||
|
$about = _m('The PubSubHubBub plugin pushes RSS/Atom updates '.
|
||||||
|
'to a <a href = "'.
|
||||||
|
'http://pubsubhubbub.googlecode.com/'.
|
||||||
|
'">PubSubHubBub</a> hub.');
|
||||||
|
if (!$this->enabled()) {
|
||||||
|
$about = '<span class="disabled" style="color:gray">' . $about . '</span> ' .
|
||||||
|
_m('(inactive on private site)');
|
||||||
|
}
|
||||||
$versions[] = array('name' => 'PubSubHubBub',
|
$versions[] = array('name' => 'PubSubHubBub',
|
||||||
'version' => STATUSNET_VERSION,
|
'version' => STATUSNET_VERSION,
|
||||||
'author' => 'Craig Andrews',
|
'author' => 'Craig Andrews',
|
||||||
'homepage' =>
|
'homepage' =>
|
||||||
'http://status.net/wiki/Plugin:PubSubHubBub',
|
'http://status.net/wiki/Plugin:PubSubHubBub',
|
||||||
'rawdescription' =>
|
'rawdescription' =>
|
||||||
_m('The PubSubHubBub plugin pushes RSS/Atom updates '.
|
$about);
|
||||||
'to a <a href = "'.
|
|
||||||
'http://pubsubhubbub.googlecode.com/'.
|
|
||||||
'">PubSubHubBub</a> hub.'));
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ class RealtimePlugin extends Plugin
|
|||||||
$scripts = $this->_getScripts();
|
$scripts = $this->_getScripts();
|
||||||
|
|
||||||
foreach ($scripts as $script) {
|
foreach ($scripts as $script) {
|
||||||
$action->script($script);
|
$action->script(common_path($script));
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = common_current_user();
|
$user = common_current_user();
|
||||||
|
@ -45,10 +45,12 @@ function read_input_line($prompt)
|
|||||||
if (CONSOLE_INTERACTIVE) {
|
if (CONSOLE_INTERACTIVE) {
|
||||||
if (CONSOLE_READLINE) {
|
if (CONSOLE_READLINE) {
|
||||||
$line = readline($prompt);
|
$line = readline($prompt);
|
||||||
readline_add_history($line);
|
if (trim($line) != '') {
|
||||||
if (defined('CONSOLE_HISTORY')) {
|
readline_add_history($line);
|
||||||
// Save often; it's easy to hit fatal errors.
|
if (defined('CONSOLE_HISTORY')) {
|
||||||
readline_write_history(CONSOLE_HISTORY);
|
// Save often; it's easy to hit fatal errors.
|
||||||
|
readline_write_history(CONSOLE_HISTORY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $line;
|
return $line;
|
||||||
} else {
|
} else {
|
||||||
|
@ -54,7 +54,7 @@ class ImDaemon extends SpawningDaemon
|
|||||||
|
|
||||||
common_log(LOG_INFO, 'terminating normally');
|
common_log(LOG_INFO, 'terminating normally');
|
||||||
|
|
||||||
return true;
|
return $master->respawn ? self::EXIT_RESTART : self::EXIT_SHUTDOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
85
scripts/queuectl.php
Executable file
85
scripts/queuectl.php
Executable file
@ -0,0 +1,85 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends control signals to running queue daemons.
|
||||||
|
*
|
||||||
|
* @author Brion Vibber <brion@status.net>
|
||||||
|
* @package QueueHandler
|
||||||
|
*/
|
||||||
|
|
||||||
|
define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
|
||||||
|
|
||||||
|
$shortoptions = 'ur';
|
||||||
|
$longoptions = array('update', 'restart', 'stop');
|
||||||
|
|
||||||
|
$helptext = <<<END_OF_QUEUECTL_HELP
|
||||||
|
Send broadcast events to control any running queue handlers.
|
||||||
|
(Currently for Stomp queues only.)
|
||||||
|
|
||||||
|
Events relating to current site (as selected with -s etc)
|
||||||
|
-u --update Announce new site or updated configuration. Running
|
||||||
|
daemons will start subscribing to any new queues needed
|
||||||
|
for this site.
|
||||||
|
|
||||||
|
Global events:
|
||||||
|
-r --restart Graceful restart of all threads
|
||||||
|
--stop Graceful shutdown of all threads
|
||||||
|
|
||||||
|
END_OF_QUEUECTL_HELP;
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/scripts/commandline.inc';
|
||||||
|
|
||||||
|
function doSendControl($message, $event, $param='')
|
||||||
|
{
|
||||||
|
print $message;
|
||||||
|
$qm = QueueManager::get();
|
||||||
|
if ($qm->sendControlSignal($event, $param)) {
|
||||||
|
print " sent.\n";
|
||||||
|
} else {
|
||||||
|
print " FAILED.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$actions = 0;
|
||||||
|
|
||||||
|
if (have_option('u') || have_option('--update')) {
|
||||||
|
$nickname = common_config('site', 'nickname');
|
||||||
|
doSendControl("Sending site update signal to queue daemons for $nickname",
|
||||||
|
"update", $nickname);
|
||||||
|
$actions++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_option('r') || have_option('--restart')) {
|
||||||
|
doSendControl("Sending graceful restart signal to queue daemons...",
|
||||||
|
"restart");
|
||||||
|
$actions++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_option('--stop')) {
|
||||||
|
doSendControl("Sending graceful shutdown signal to queue daemons...",
|
||||||
|
"shutdown");
|
||||||
|
$actions++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$actions) {
|
||||||
|
show_help();
|
||||||
|
}
|
||||||
|
|
@ -115,7 +115,7 @@ class QueueDaemon extends SpawningDaemon
|
|||||||
|
|
||||||
$this->log(LOG_INFO, 'terminating normally');
|
$this->log(LOG_INFO, 'terminating normally');
|
||||||
|
|
||||||
return true;
|
return $master->respawn ? self::EXIT_RESTART : self::EXIT_SHUTDOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
115
tests/oauth/statusupdate.php
Normal file
115
tests/oauth/statusupdate.php
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* StatusNet - a 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/>.
|
||||||
|
**/
|
||||||
|
|
||||||
|
define('INSTALLDIR', realpath(dirname(__FILE__) . '/../..'));
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/extlib/OAuth.php';
|
||||||
|
|
||||||
|
$shortoptions = 'o:s:u:';
|
||||||
|
$longoptions = array('oauth_token=', 'token_secret=', 'update=');
|
||||||
|
|
||||||
|
$helptext = <<<END_OF_VERIFY_HELP
|
||||||
|
statusupdate.php [options]
|
||||||
|
Update your status using OAuth
|
||||||
|
|
||||||
|
-o --oauth_token access token
|
||||||
|
-s --token_secret access token secret
|
||||||
|
-u --update status update
|
||||||
|
|
||||||
|
|
||||||
|
END_OF_VERIFY_HELP;
|
||||||
|
|
||||||
|
$token = null;
|
||||||
|
$token_secret = null;
|
||||||
|
$update = null;
|
||||||
|
|
||||||
|
require_once INSTALLDIR . '/scripts/commandline.inc';
|
||||||
|
|
||||||
|
if (have_option('o', 'oauth_token')) {
|
||||||
|
$token = get_option_value('oauth_token');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_option('s', 'token_secret')) {
|
||||||
|
$token_secret = get_option_value('s', 'token_secret');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_option('u', 'update')) {
|
||||||
|
$update = get_option_value('u', 'update');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($token)) {
|
||||||
|
print "Please specify an access token.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($token_secret)) {
|
||||||
|
print "Please specify an access token secret.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($update)) {
|
||||||
|
print "You forgot to update your status!\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ini = parse_ini_file("oauth.ini");
|
||||||
|
|
||||||
|
$test_consumer = new OAuthConsumer($ini['consumer_key'], $ini['consumer_secret']);
|
||||||
|
|
||||||
|
$endpoint = $ini['apiroot'] . '/statuses/update.xml';
|
||||||
|
|
||||||
|
print "$endpoint\n";
|
||||||
|
|
||||||
|
$at = new OAuthToken($token, $token_secret);
|
||||||
|
|
||||||
|
$parsed = parse_url($endpoint);
|
||||||
|
$params = array();
|
||||||
|
parse_str($parsed['query'], $params);
|
||||||
|
|
||||||
|
$params['status'] = $update;
|
||||||
|
|
||||||
|
$hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
|
||||||
|
|
||||||
|
$req_req = OAuthRequest::from_consumer_and_token($test_consumer, $at, 'POST', $endpoint, $params);
|
||||||
|
$req_req->sign_request($hmac_method, $test_consumer, $at);
|
||||||
|
|
||||||
|
$r = httpRequest($req_req->to_url());
|
||||||
|
|
||||||
|
$body = $r->getBody();
|
||||||
|
|
||||||
|
print "$body\n";
|
||||||
|
|
||||||
|
//print $req_req->to_url() . "\n\n";
|
||||||
|
|
||||||
|
function httpRequest($url)
|
||||||
|
{
|
||||||
|
$request = HTTPClient::start();
|
||||||
|
|
||||||
|
$request->setConfig(array(
|
||||||
|
'follow_redirects' => true,
|
||||||
|
'connect_timeout' => 120,
|
||||||
|
'timeout' => 120,
|
||||||
|
'ssl_verify_peer' => false,
|
||||||
|
'ssl_verify_host' => false
|
||||||
|
));
|
||||||
|
|
||||||
|
return $request->post($url);
|
||||||
|
}
|
||||||
|
|
54
theme/base/css/uap.css
Normal file
54
theme/base/css/uap.css
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/** Universal Ad Package styles:
|
||||||
|
* Medium Rectangle 300x250
|
||||||
|
* Rectangle 180x150
|
||||||
|
* Leaderboard 728x90
|
||||||
|
* Wide Skyscraper 160x600
|
||||||
|
*
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Sarven Capadisli <csarven@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/
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
.ad {
|
||||||
|
border:1px solid #CCC;
|
||||||
|
float:left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ad_medium-rectangle {
|
||||||
|
width:300px;
|
||||||
|
height:250px;
|
||||||
|
|
||||||
|
margin-left:1.35%;
|
||||||
|
margin-bottom:18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ad_rectangle {
|
||||||
|
width:180px;
|
||||||
|
height:150px;
|
||||||
|
|
||||||
|
float:none;
|
||||||
|
clear:both;
|
||||||
|
margin:0 auto;
|
||||||
|
margin-bottom:29px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ad_leaderboard {
|
||||||
|
width:728px;
|
||||||
|
height:90px;
|
||||||
|
|
||||||
|
margin:0 auto 18px;
|
||||||
|
float:none;
|
||||||
|
clear:both;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ad_wide-skyscraper {
|
||||||
|
width:160px;
|
||||||
|
height:600px;
|
||||||
|
|
||||||
|
float:right;
|
||||||
|
margin-top:18px;
|
||||||
|
margin-right:8.25%;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user