forked from GNUsocial/gnu-social
Merge branch 'testing' of git@gitorious.org:statusnet/mainline into testing
This commit is contained in:
commit
7558e2fd61
15
EVENTS.txt
15
EVENTS.txt
@ -699,3 +699,18 @@ StartShowContentLicense: Showing the default license for content
|
|||||||
|
|
||||||
EndShowContentLicense: Showing the default license for content
|
EndShowContentLicense: Showing the default license for content
|
||||||
- $action: the current action
|
- $action: the current action
|
||||||
|
|
||||||
|
StartUserRegister: When a new user is being registered
|
||||||
|
- &$profile: new profile data (no ID)
|
||||||
|
- &$user: new user account (no ID or URI)
|
||||||
|
|
||||||
|
EndUserRegister: When a new user has been registered
|
||||||
|
- &$profile: new profile data
|
||||||
|
- &$user: new user account
|
||||||
|
|
||||||
|
StartRobotsTxt: Before outputting the robots.txt page
|
||||||
|
- &$action: RobotstxtAction being shown
|
||||||
|
|
||||||
|
EndRobotsTxt: After the default robots.txt page (good place for customization)
|
||||||
|
- &$action: RobotstxtAction being shown
|
||||||
|
|
||||||
|
14
README
14
README
@ -1496,6 +1496,20 @@ interface. It also makes the user's profile the root URL.
|
|||||||
enabled: Whether to run in "single user mode". Default false.
|
enabled: Whether to run in "single user mode". Default false.
|
||||||
nickname: nickname of the single user.
|
nickname: nickname of the single user.
|
||||||
|
|
||||||
|
robotstxt
|
||||||
|
---------
|
||||||
|
|
||||||
|
We put out a default robots.txt file to guide the processing of
|
||||||
|
Web crawlers. See http://www.robotstxt.org/ for more information
|
||||||
|
on the format of this file.
|
||||||
|
|
||||||
|
crawldelay: if non-empty, this value is provided as the Crawl-Delay:
|
||||||
|
for the robots.txt file. see http://ur1.ca/l5a0
|
||||||
|
for more information. Default is zero, no explicit delay.
|
||||||
|
disallow: Array of (virtual) directories to disallow. Default is 'main',
|
||||||
|
'search', 'message', 'settings', 'admin'. Ignored when site
|
||||||
|
is private, in which case the entire site ('/') is disallowed.
|
||||||
|
|
||||||
Plugins
|
Plugins
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
@ -42,6 +42,10 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
|
|||||||
*/
|
*/
|
||||||
class GeocodeAction extends Action
|
class GeocodeAction extends Action
|
||||||
{
|
{
|
||||||
|
var $lat = null;
|
||||||
|
var $lon = null;
|
||||||
|
var $location = null;
|
||||||
|
|
||||||
function prepare($args)
|
function prepare($args)
|
||||||
{
|
{
|
||||||
parent::prepare($args);
|
parent::prepare($args);
|
||||||
@ -52,12 +56,7 @@ class GeocodeAction extends Action
|
|||||||
}
|
}
|
||||||
$this->lat = $this->trimmed('lat');
|
$this->lat = $this->trimmed('lat');
|
||||||
$this->lon = $this->trimmed('lon');
|
$this->lon = $this->trimmed('lon');
|
||||||
$location = Location::fromLatLon($this->lat, $this->lon);
|
$this->location = Location::fromLatLon($this->lat, $this->lon);
|
||||||
if ($location) {
|
|
||||||
$this->location = Location::fromId($location->location_id, $location->location_ns);
|
|
||||||
$this->lat = $this->location->lat;
|
|
||||||
$this->lon = $this->location->lon;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,4 +94,3 @@ class GeocodeAction extends Action
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
@ -137,6 +137,14 @@ class PublicAction extends Action
|
|||||||
parent::extraHead();
|
parent::extraHead();
|
||||||
$this->element('meta', array('http-equiv' => 'X-XRDS-Location',
|
$this->element('meta', array('http-equiv' => 'X-XRDS-Location',
|
||||||
'content' => common_local_url('publicxrds')));
|
'content' => common_local_url('publicxrds')));
|
||||||
|
|
||||||
|
$rsd = common_local_url('rsd');
|
||||||
|
|
||||||
|
// RSD, http://tales.phrasewise.com/rfc/rsd
|
||||||
|
|
||||||
|
$this->element('link', array('rel' => 'EditURI',
|
||||||
|
'type' => 'application/rsd+xml',
|
||||||
|
'href' => $rsd));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
100
actions/robotstxt.php
Normal file
100
actions/robotstxt.php
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet - the distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2010, StatusNet, Inc.
|
||||||
|
*
|
||||||
|
* robots.txt generator
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* @category Action
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||||
|
* @link http://status.net/
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints out a static robots.txt
|
||||||
|
*
|
||||||
|
* @category Action
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
class RobotstxtAction extends Action
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handles requests
|
||||||
|
*
|
||||||
|
* Since this is a relatively static document, we
|
||||||
|
* don't do a prepare()
|
||||||
|
*
|
||||||
|
* @param array $args GET, POST, and URL params; unused.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
if (Event::handle('StartRobotsTxt', array($this))) {
|
||||||
|
|
||||||
|
header('Content-Type: text/plain');
|
||||||
|
|
||||||
|
print "User-Agent: *\n";
|
||||||
|
|
||||||
|
if (common_config('site', 'private')) {
|
||||||
|
|
||||||
|
print "Disallow: /\n";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$disallow = common_config('robotstxt', 'disallow');
|
||||||
|
|
||||||
|
foreach ($disallow as $dir) {
|
||||||
|
print "Disallow: /$dir/\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$crawldelay = common_config('robotstxt', 'crawldelay');
|
||||||
|
|
||||||
|
if (!empty($crawldelay)) {
|
||||||
|
print "Crawl-delay: " . $crawldelay . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::handle('EndRobotsTxt', array($this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true; this page doesn't touch the DB.
|
||||||
|
*
|
||||||
|
* @param array $args other arguments
|
||||||
|
*
|
||||||
|
* @return boolean is read only action?
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
226
actions/rsd.php
Normal file
226
actions/rsd.php
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet - the distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2008-2010, StatusNet, Inc.
|
||||||
|
*
|
||||||
|
* Really Simple Discovery (RSD) for API access
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||||
|
* @link http://status.net/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSD action class
|
||||||
|
*
|
||||||
|
* Really Simple Discovery (RSD) is a simple (to a fault, maybe)
|
||||||
|
* discovery tool for blog APIs.
|
||||||
|
*
|
||||||
|
* http://tales.phrasewise.com/rfc/rsd
|
||||||
|
*
|
||||||
|
* Anil Dash suggested that RSD be used for services that implement
|
||||||
|
* the Twitter API:
|
||||||
|
*
|
||||||
|
* http://dashes.com/anil/2009/12/the-twitter-api-is-finished.html
|
||||||
|
*
|
||||||
|
* It's in use now for WordPress.com blogs:
|
||||||
|
*
|
||||||
|
* http://matt.wordpress.com/xmlrpc.php?rsd
|
||||||
|
*
|
||||||
|
* I (evan@status.net) have tried to stay faithful to the premise of
|
||||||
|
* RSD, while adding information useful to StatusNet client developers.
|
||||||
|
* In particular:
|
||||||
|
*
|
||||||
|
* - There is a link from each user's profile page to their personal
|
||||||
|
* RSD feed. A personal rsd.xml includes a 'blogID' element that is
|
||||||
|
* their username.
|
||||||
|
* - There is a link from the public root to '/rsd.xml', a public RSD
|
||||||
|
* feed. It's identical to the personal rsd except it doesn't include
|
||||||
|
* a blogId.
|
||||||
|
* - I've added a setting to the API to indicate that OAuth support is
|
||||||
|
* available.
|
||||||
|
*
|
||||||
|
* @category API
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
class RsdAction extends Action
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Optional attribute for the personal rsd.xml file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var $user = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the action for use.
|
||||||
|
*
|
||||||
|
* Check for a nickname; redirect if non-canonical; if
|
||||||
|
* not provided, assume public rsd.xml.
|
||||||
|
*
|
||||||
|
* @param array $args GET, POST, and URI arguments.
|
||||||
|
*
|
||||||
|
* @return boolean success flag
|
||||||
|
*/
|
||||||
|
|
||||||
|
function prepare($args)
|
||||||
|
{
|
||||||
|
parent::prepare($args);
|
||||||
|
|
||||||
|
// optional argument
|
||||||
|
|
||||||
|
$nickname_arg = $this->arg('nickname');
|
||||||
|
|
||||||
|
if (empty($nickname_arg)) {
|
||||||
|
$this->user = null;
|
||||||
|
} else {
|
||||||
|
$nickname = common_canonical_nickname($nickname_arg);
|
||||||
|
|
||||||
|
// Permanent redirect on non-canonical nickname
|
||||||
|
|
||||||
|
if ($nickname_arg != $nickname) {
|
||||||
|
common_redirect(common_local_url('rsd',
|
||||||
|
array('nickname' => $nickname)),
|
||||||
|
301);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->user = User::staticGet('nickname', $nickname);
|
||||||
|
|
||||||
|
if (empty($this->user)) {
|
||||||
|
$this->clientError(_('No such user.'), 404);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action handler.
|
||||||
|
*
|
||||||
|
* Outputs the XML format for an RSD file. May include
|
||||||
|
* personal information if this is a personal file
|
||||||
|
* (based on whether $user attribute is set).
|
||||||
|
*
|
||||||
|
* @param array $args array of arguments
|
||||||
|
*
|
||||||
|
* @return nothing
|
||||||
|
*/
|
||||||
|
|
||||||
|
function handle($args)
|
||||||
|
{
|
||||||
|
header('Content-Type: application/rsd+xml');
|
||||||
|
|
||||||
|
$this->startXML();
|
||||||
|
|
||||||
|
$rsdNS = 'http://archipelago.phrasewise.com/rsd';
|
||||||
|
$this->elementStart('rsd', array('version' => '1.0',
|
||||||
|
'xmlns' => $rsdNS));
|
||||||
|
$this->elementStart('service');
|
||||||
|
$this->element('engineName', null, _('StatusNet'));
|
||||||
|
$this->element('engineLink', null, 'http://status.net/');
|
||||||
|
$this->elementStart('apis');
|
||||||
|
if (Event::handle('StartRsdListApis', array($this, $this->user))) {
|
||||||
|
|
||||||
|
$blogID = (empty($this->user)) ? '' : $this->user->nickname;
|
||||||
|
$apiAttrs = array('name' => 'Twitter',
|
||||||
|
'preferred' => 'true',
|
||||||
|
'apiLink' => $this->_apiRoot(),
|
||||||
|
'blogID' => $blogID);
|
||||||
|
|
||||||
|
$this->elementStart('api', $apiAttrs);
|
||||||
|
$this->elementStart('settings');
|
||||||
|
$this->element('docs', null,
|
||||||
|
'http://status.net/wiki/TwitterCompatibleAPI');
|
||||||
|
$this->element('setting', array('name' => 'OAuth'),
|
||||||
|
'true');
|
||||||
|
$this->elementEnd('settings');
|
||||||
|
$this->elementEnd('api');
|
||||||
|
Event::handle('EndRsdListApis', array($this, $this->user));
|
||||||
|
}
|
||||||
|
$this->elementEnd('apis');
|
||||||
|
$this->elementEnd('service');
|
||||||
|
$this->elementEnd('rsd');
|
||||||
|
|
||||||
|
$this->endXML();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns last-modified date for use in caching
|
||||||
|
*
|
||||||
|
* Per-user rsd.xml is dated to last change of user
|
||||||
|
* (in case of nickname change); public has no date.
|
||||||
|
*
|
||||||
|
* @return string date of last change of this page
|
||||||
|
*/
|
||||||
|
|
||||||
|
function lastModified()
|
||||||
|
{
|
||||||
|
if (!empty($this->user)) {
|
||||||
|
return $this->user->modified;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag to indicate if this action is read-only
|
||||||
|
*
|
||||||
|
* It is; it doesn't change the DB.
|
||||||
|
*
|
||||||
|
* @param array $args ignored
|
||||||
|
*
|
||||||
|
* @return boolean true
|
||||||
|
*/
|
||||||
|
|
||||||
|
function isReadOnly($args)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return current site's API root
|
||||||
|
*
|
||||||
|
* Varies based on URL parameters, like if fancy URLs are
|
||||||
|
* turned on.
|
||||||
|
*
|
||||||
|
* @return string API root URI for this site
|
||||||
|
*/
|
||||||
|
|
||||||
|
private function _apiRoot()
|
||||||
|
{
|
||||||
|
if (common_config('site', 'fancy')) {
|
||||||
|
return common_path('api/', true);
|
||||||
|
} else {
|
||||||
|
return common_path('index.php/api/', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -178,6 +178,15 @@ class ShowstreamAction extends ProfileAction
|
|||||||
$this->element('link', array('rel' => 'microsummary',
|
$this->element('link', array('rel' => 'microsummary',
|
||||||
'href' => common_local_url('microsummary',
|
'href' => common_local_url('microsummary',
|
||||||
array('nickname' => $this->profile->nickname))));
|
array('nickname' => $this->profile->nickname))));
|
||||||
|
|
||||||
|
$rsd = common_local_url('rsd',
|
||||||
|
array('nickname' => $this->profile->nickname));
|
||||||
|
|
||||||
|
// RSD, http://tales.phrasewise.com/rfc/rsd
|
||||||
|
$this->element('link', array('rel' => 'EditURI',
|
||||||
|
'type' => 'application/rsd+xml',
|
||||||
|
'href' => $rsd));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showProfile()
|
function showProfile()
|
||||||
|
@ -552,4 +552,30 @@ class Memcached_DataObject extends DB_DataObject
|
|||||||
{
|
{
|
||||||
throw new ServerException("DB_DataObject error [$type]: $message");
|
throw new ServerException("DB_DataObject error [$type]: $message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function cacheGet($keyPart)
|
||||||
|
{
|
||||||
|
$c = self::memcache();
|
||||||
|
|
||||||
|
if (empty($c)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cacheKey = common_cache_key($keyPart);
|
||||||
|
|
||||||
|
return $c->get($cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function cacheSet($keyPart, $value)
|
||||||
|
{
|
||||||
|
$c = self::memcache();
|
||||||
|
|
||||||
|
if (empty($c)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cacheKey = common_cache_key($keyPart);
|
||||||
|
|
||||||
|
return $c->set($cacheKey, $value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ class Notice extends Memcached_DataObject
|
|||||||
foreach(array_unique($hashtags) as $hashtag) {
|
foreach(array_unique($hashtags) as $hashtag) {
|
||||||
/* elide characters we don't want in the tag */
|
/* elide characters we don't want in the tag */
|
||||||
$this->saveTag($hashtag);
|
$this->saveTag($hashtag);
|
||||||
self::blow('profile:notice_ids_tagged:%d:%s', $this->profile_id, $tag->tag);
|
self::blow('profile:notice_ids_tagged:%d:%s', $this->profile_id, $hashtag);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ class Profile_role extends Memcached_DataObject
|
|||||||
return Memcached_DataObject::pkeyGet('Profile_role', $kv);
|
return Memcached_DataObject::pkeyGet('Profile_role', $kv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const OWNER = 'owner';
|
||||||
const MODERATOR = 'moderator';
|
const MODERATOR = 'moderator';
|
||||||
const ADMINISTRATOR = 'administrator';
|
const ADMINISTRATOR = 'administrator';
|
||||||
const SANDBOXED = 'sandboxed';
|
const SANDBOXED = 'sandboxed';
|
||||||
|
225
classes/User.php
225
classes/User.php
@ -209,8 +209,6 @@ class User extends Memcached_DataObject
|
|||||||
|
|
||||||
$profile = new Profile();
|
$profile = new Profile();
|
||||||
|
|
||||||
$profile->query('BEGIN');
|
|
||||||
|
|
||||||
if(!empty($email))
|
if(!empty($email))
|
||||||
{
|
{
|
||||||
$email = common_canonical_email($email);
|
$email = common_canonical_email($email);
|
||||||
@ -220,7 +218,7 @@ class User extends Memcached_DataObject
|
|||||||
$profile->nickname = $nickname;
|
$profile->nickname = $nickname;
|
||||||
if(! User::allowed_nickname($nickname)){
|
if(! User::allowed_nickname($nickname)){
|
||||||
common_log(LOG_WARNING, sprintf("Attempted to register a nickname that is not allowed: %s", $profile->nickname),
|
common_log(LOG_WARNING, sprintf("Attempted to register a nickname that is not allowed: %s", $profile->nickname),
|
||||||
__FILE__);
|
__FILE__);
|
||||||
}
|
}
|
||||||
$profile->profileurl = common_profile_url($nickname);
|
$profile->profileurl = common_profile_url($nickname);
|
||||||
|
|
||||||
@ -248,16 +246,8 @@ class User extends Memcached_DataObject
|
|||||||
|
|
||||||
$profile->created = common_sql_now();
|
$profile->created = common_sql_now();
|
||||||
|
|
||||||
$id = $profile->insert();
|
|
||||||
|
|
||||||
if (empty($id)) {
|
|
||||||
common_log_db_error($profile, 'INSERT', __FILE__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$user = new User();
|
$user = new User();
|
||||||
|
|
||||||
$user->id = $id;
|
|
||||||
$user->nickname = $nickname;
|
$user->nickname = $nickname;
|
||||||
|
|
||||||
if (!empty($password)) { // may not have a password for OpenID users
|
if (!empty($password)) { // may not have a password for OpenID users
|
||||||
@ -282,109 +272,126 @@ class User extends Memcached_DataObject
|
|||||||
$user->inboxed = 1;
|
$user->inboxed = 1;
|
||||||
|
|
||||||
$user->created = common_sql_now();
|
$user->created = common_sql_now();
|
||||||
$user->uri = common_user_uri($user);
|
|
||||||
|
|
||||||
$result = $user->insert();
|
if (Event::handle('StartUserRegister', array(&$user, &$profile))) {
|
||||||
|
|
||||||
if (!$result) {
|
$profile->query('BEGIN');
|
||||||
common_log_db_error($user, 'INSERT', __FILE__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Everyone gets an inbox
|
$id = $profile->insert();
|
||||||
|
|
||||||
$inbox = new Inbox();
|
if (empty($id)) {
|
||||||
|
common_log_db_error($profile, 'INSERT', __FILE__);
|
||||||
$inbox->user_id = $user->id;
|
|
||||||
$inbox->notice_ids = '';
|
|
||||||
|
|
||||||
$result = $inbox->insert();
|
|
||||||
|
|
||||||
if (!$result) {
|
|
||||||
common_log_db_error($inbox, 'INSERT', __FILE__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Everyone is subscribed to themself
|
|
||||||
|
|
||||||
$subscription = new Subscription();
|
|
||||||
$subscription->subscriber = $user->id;
|
|
||||||
$subscription->subscribed = $user->id;
|
|
||||||
$subscription->created = $user->created;
|
|
||||||
|
|
||||||
$result = $subscription->insert();
|
|
||||||
|
|
||||||
if (!$result) {
|
|
||||||
common_log_db_error($subscription, 'INSERT', __FILE__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($email) && !$user->email) {
|
|
||||||
|
|
||||||
$confirm = new Confirm_address();
|
|
||||||
$confirm->code = common_confirmation_code(128);
|
|
||||||
$confirm->user_id = $user->id;
|
|
||||||
$confirm->address = $email;
|
|
||||||
$confirm->address_type = 'email';
|
|
||||||
|
|
||||||
$result = $confirm->insert();
|
|
||||||
if (!$result) {
|
|
||||||
common_log_db_error($confirm, 'INSERT', __FILE__);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($code) && $user->email) {
|
$user->id = $id;
|
||||||
$user->emailChanged();
|
$user->uri = common_user_uri($user);
|
||||||
}
|
|
||||||
|
|
||||||
// Default system subscription
|
$result = $user->insert();
|
||||||
|
|
||||||
$defnick = common_config('newuser', 'default');
|
if (!$result) {
|
||||||
|
common_log_db_error($user, 'INSERT', __FILE__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!empty($defnick)) {
|
// Everyone gets an inbox
|
||||||
$defuser = User::staticGet('nickname', $defnick);
|
|
||||||
if (empty($defuser)) {
|
|
||||||
common_log(LOG_WARNING, sprintf("Default user %s does not exist.", $defnick),
|
|
||||||
__FILE__);
|
|
||||||
} else {
|
|
||||||
$defsub = new Subscription();
|
|
||||||
$defsub->subscriber = $user->id;
|
|
||||||
$defsub->subscribed = $defuser->id;
|
|
||||||
$defsub->created = $user->created;
|
|
||||||
|
|
||||||
$result = $defsub->insert();
|
$inbox = new Inbox();
|
||||||
|
|
||||||
|
$inbox->user_id = $user->id;
|
||||||
|
$inbox->notice_ids = '';
|
||||||
|
|
||||||
|
$result = $inbox->insert();
|
||||||
|
|
||||||
|
if (!$result) {
|
||||||
|
common_log_db_error($inbox, 'INSERT', __FILE__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everyone is subscribed to themself
|
||||||
|
|
||||||
|
$subscription = new Subscription();
|
||||||
|
$subscription->subscriber = $user->id;
|
||||||
|
$subscription->subscribed = $user->id;
|
||||||
|
$subscription->created = $user->created;
|
||||||
|
|
||||||
|
$result = $subscription->insert();
|
||||||
|
|
||||||
|
if (!$result) {
|
||||||
|
common_log_db_error($subscription, 'INSERT', __FILE__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($email) && !$user->email) {
|
||||||
|
|
||||||
|
$confirm = new Confirm_address();
|
||||||
|
$confirm->code = common_confirmation_code(128);
|
||||||
|
$confirm->user_id = $user->id;
|
||||||
|
$confirm->address = $email;
|
||||||
|
$confirm->address_type = 'email';
|
||||||
|
|
||||||
|
$result = $confirm->insert();
|
||||||
|
|
||||||
if (!$result) {
|
if (!$result) {
|
||||||
common_log_db_error($defsub, 'INSERT', __FILE__);
|
common_log_db_error($confirm, 'INSERT', __FILE__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$profile->query('COMMIT');
|
|
||||||
|
|
||||||
if (!empty($email) && !$user->email) {
|
|
||||||
mail_confirm_address($user, $confirm->code, $profile->nickname, $email);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Welcome message
|
|
||||||
|
|
||||||
$welcome = common_config('newuser', 'welcome');
|
|
||||||
|
|
||||||
if (!empty($welcome)) {
|
|
||||||
$welcomeuser = User::staticGet('nickname', $welcome);
|
|
||||||
if (empty($welcomeuser)) {
|
|
||||||
common_log(LOG_WARNING, sprintf("Welcome user %s does not exist.", $defnick),
|
|
||||||
__FILE__);
|
|
||||||
} else {
|
|
||||||
$notice = Notice::saveNew($welcomeuser->id,
|
|
||||||
sprintf(_('Welcome to %1$s, @%2$s!'),
|
|
||||||
common_config('site', 'name'),
|
|
||||||
$user->nickname),
|
|
||||||
'system');
|
|
||||||
|
|
||||||
|
if (!empty($code) && $user->email) {
|
||||||
|
$user->emailChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default system subscription
|
||||||
|
|
||||||
|
$defnick = common_config('newuser', 'default');
|
||||||
|
|
||||||
|
if (!empty($defnick)) {
|
||||||
|
$defuser = User::staticGet('nickname', $defnick);
|
||||||
|
if (empty($defuser)) {
|
||||||
|
common_log(LOG_WARNING, sprintf("Default user %s does not exist.", $defnick),
|
||||||
|
__FILE__);
|
||||||
|
} else {
|
||||||
|
$defsub = new Subscription();
|
||||||
|
$defsub->subscriber = $user->id;
|
||||||
|
$defsub->subscribed = $defuser->id;
|
||||||
|
$defsub->created = $user->created;
|
||||||
|
|
||||||
|
$result = $defsub->insert();
|
||||||
|
|
||||||
|
if (!$result) {
|
||||||
|
common_log_db_error($defsub, 'INSERT', __FILE__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$profile->query('COMMIT');
|
||||||
|
|
||||||
|
if (!empty($email) && !$user->email) {
|
||||||
|
mail_confirm_address($user, $confirm->code, $profile->nickname, $email);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Welcome message
|
||||||
|
|
||||||
|
$welcome = common_config('newuser', 'welcome');
|
||||||
|
|
||||||
|
if (!empty($welcome)) {
|
||||||
|
$welcomeuser = User::staticGet('nickname', $welcome);
|
||||||
|
if (empty($welcomeuser)) {
|
||||||
|
common_log(LOG_WARNING, sprintf("Welcome user %s does not exist.", $defnick),
|
||||||
|
__FILE__);
|
||||||
|
} else {
|
||||||
|
$notice = Notice::saveNew($welcomeuser->id,
|
||||||
|
sprintf(_('Welcome to %1$s, @%2$s!'),
|
||||||
|
common_config('site', 'name'),
|
||||||
|
$user->nickname),
|
||||||
|
'system');
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Event::handle('EndUserRegister', array(&$profile, &$user));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $user;
|
return $user;
|
||||||
@ -925,4 +932,30 @@ class User extends Memcached_DataObject
|
|||||||
return $share;
|
return $share;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function siteOwner()
|
||||||
|
{
|
||||||
|
$owner = self::cacheGet('user:site_owner');
|
||||||
|
|
||||||
|
if ($owner === false) { // cache miss
|
||||||
|
|
||||||
|
$pr = new Profile_role();
|
||||||
|
|
||||||
|
$pr->role = Profile_role::OWNER;
|
||||||
|
|
||||||
|
$pr->orderBy('created');
|
||||||
|
|
||||||
|
$pr->limit(0, 1);
|
||||||
|
|
||||||
|
if ($pr->fetch($true)) {
|
||||||
|
$owner = User::staticGet('id', $pr->profile_id);
|
||||||
|
} else {
|
||||||
|
$owner = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::cacheSet('user:site_owner', $owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $owner;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ theme = 2
|
|||||||
logo = 2
|
logo = 2
|
||||||
created = 142
|
created = 142
|
||||||
modified = 384
|
modified = 384
|
||||||
|
tags = 34
|
||||||
|
|
||||||
[status_network__keys]
|
[status_network__keys]
|
||||||
nickname = K
|
nickname = K
|
||||||
|
18
index.php
18
index.php
@ -146,7 +146,7 @@ function formatBacktraceLine($n, $line)
|
|||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkMirror($action_obj, $args)
|
function setupRW()
|
||||||
{
|
{
|
||||||
global $config;
|
global $config;
|
||||||
|
|
||||||
@ -161,6 +161,11 @@ function checkMirror($action_obj, $args)
|
|||||||
foreach ($alwaysRW as $table) {
|
foreach ($alwaysRW as $table) {
|
||||||
$config['db']['table_'.$table] = 'rw';
|
$config['db']['table_'.$table] = 'rw';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkMirror($action_obj, $args)
|
||||||
|
{
|
||||||
|
global $config;
|
||||||
|
|
||||||
if (common_config('db', 'mirror') && $action_obj->isReadOnly($args)) {
|
if (common_config('db', 'mirror') && $action_obj->isReadOnly($args)) {
|
||||||
if (is_array(common_config('db', 'mirror'))) {
|
if (is_array(common_config('db', 'mirror'))) {
|
||||||
@ -237,9 +242,13 @@ function main()
|
|||||||
|
|
||||||
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'handleError');
|
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'handleError');
|
||||||
|
|
||||||
|
// Make sure RW database is setup
|
||||||
|
|
||||||
|
setupRW();
|
||||||
|
|
||||||
// XXX: we need a little more structure in this script
|
// XXX: we need a little more structure in this script
|
||||||
|
|
||||||
// get and cache current user
|
// get and cache current user (may hit RW!)
|
||||||
|
|
||||||
$user = common_current_user();
|
$user = common_current_user();
|
||||||
|
|
||||||
@ -276,8 +285,9 @@ function main()
|
|||||||
if (!$user && common_config('site', 'private')
|
if (!$user && common_config('site', 'private')
|
||||||
&& !isLoginAction($action)
|
&& !isLoginAction($action)
|
||||||
&& !preg_match('/rss$/', $action)
|
&& !preg_match('/rss$/', $action)
|
||||||
&& !preg_match('/^Api/', $action)
|
&& $action != 'robotstxt'
|
||||||
) {
|
&& !preg_match('/^Api/', $action)) {
|
||||||
|
|
||||||
// set returnto
|
// set returnto
|
||||||
$rargs =& common_copy_args($args);
|
$rargs =& common_copy_args($args);
|
||||||
unset($rargs['action']);
|
unset($rargs['action']);
|
||||||
|
@ -298,7 +298,7 @@ class ApiAction extends Action
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($include_user) {
|
if ($include_user && $profile) {
|
||||||
# Don't get notice (recursive!)
|
# Don't get notice (recursive!)
|
||||||
$twitter_user = $this->twitterUserArray($profile, false);
|
$twitter_user = $this->twitterUserArray($profile, false);
|
||||||
$twitter_status['user'] = $twitter_user;
|
$twitter_status['user'] = $twitter_user;
|
||||||
|
@ -270,4 +270,8 @@ $default =
|
|||||||
'singleuser' =>
|
'singleuser' =>
|
||||||
array('enabled' => false,
|
array('enabled' => false,
|
||||||
'nickname' => null),
|
'nickname' => null),
|
||||||
|
'robotstxt' =>
|
||||||
|
array('crawldelay' => 0,
|
||||||
|
'disallow' => array('main', 'settings', 'admin', 'search', 'message')
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
@ -62,23 +62,60 @@ class DistribQueueHandler
|
|||||||
{
|
{
|
||||||
// XXX: do we need to change this for remote users?
|
// XXX: do we need to change this for remote users?
|
||||||
|
|
||||||
$notice->saveTags();
|
try {
|
||||||
|
$notice->saveTags();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->logit($notice, $e);
|
||||||
|
}
|
||||||
|
|
||||||
$groups = $notice->saveGroups();
|
try {
|
||||||
|
$groups = $notice->saveGroups();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->logit($notice, $e);
|
||||||
|
}
|
||||||
|
|
||||||
$recipients = $notice->saveReplies();
|
try {
|
||||||
|
$recipients = $notice->saveReplies();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->logit($notice, $e);
|
||||||
|
}
|
||||||
|
|
||||||
$notice->addToInboxes($groups, $recipients);
|
try {
|
||||||
|
$notice->addToInboxes($groups, $recipients);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->logit($notice, $e);
|
||||||
|
}
|
||||||
|
|
||||||
$notice->saveUrls();
|
try {
|
||||||
|
$notice->saveUrls();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->logit($notice, $e);
|
||||||
|
}
|
||||||
|
|
||||||
Event::handle('EndNoticeSave', array($notice));
|
try {
|
||||||
|
Event::handle('EndNoticeSave', array($notice));
|
||||||
|
// Enqueue for other handlers
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->logit($notice, $e);
|
||||||
|
}
|
||||||
|
|
||||||
// Enqueue for other handlers
|
try {
|
||||||
|
common_enqueue_notice($notice);
|
||||||
common_enqueue_notice($notice);
|
} catch (Exception $e) {
|
||||||
|
$this->logit($notice, $e);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function logit($notice, $e)
|
||||||
|
{
|
||||||
|
common_log(LOG_ERR, "Distrib queue exception saving notice $notice->id: " .
|
||||||
|
$e->getMessage() . ' ' .
|
||||||
|
str_replace("\n", " ", $e->getTraceAsString()));
|
||||||
|
|
||||||
|
// We'll still return true so we don't get stuck in a loop
|
||||||
|
// trying to run a bad insert over and over...
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +358,7 @@ function jabber_broadcast_notice($notice)
|
|||||||
common_log(LOG_WARNING, 'Refusing to broadcast notice with ' .
|
common_log(LOG_WARNING, 'Refusing to broadcast notice with ' .
|
||||||
'unknown profile ' . common_log_objstring($notice),
|
'unknown profile ' . common_log_objstring($notice),
|
||||||
__FILE__);
|
__FILE__);
|
||||||
return false;
|
return true; // not recoverable; discard.
|
||||||
}
|
}
|
||||||
|
|
||||||
$msg = jabber_format_notice($profile, $notice);
|
$msg = jabber_format_notice($profile, $notice);
|
||||||
@ -437,7 +437,7 @@ function jabber_public_notice($notice)
|
|||||||
common_log(LOG_WARNING, 'Refusing to broadcast notice with ' .
|
common_log(LOG_WARNING, 'Refusing to broadcast notice with ' .
|
||||||
'unknown profile ' . common_log_objstring($notice),
|
'unknown profile ' . common_log_objstring($notice),
|
||||||
__FILE__);
|
__FILE__);
|
||||||
return false;
|
return true; // not recoverable; discard.
|
||||||
}
|
}
|
||||||
|
|
||||||
$msg = jabber_format_notice($profile, $notice);
|
$msg = jabber_format_notice($profile, $notice);
|
||||||
|
@ -40,7 +40,7 @@ class JabberQueueHandler extends QueueHandler
|
|||||||
try {
|
try {
|
||||||
return jabber_broadcast_notice($notice);
|
return jabber_broadcast_notice($notice);
|
||||||
} catch (XMPPHP_Exception $e) {
|
} catch (XMPPHP_Exception $e) {
|
||||||
$this->log(LOG_ERR, "Got an XMPPHP_Exception: " . $e->getMessage());
|
common_log(LOG_ERR, "Got an XMPPHP_Exception: " . $e->getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ class OmbQueueHandler extends QueueHandler
|
|||||||
function handle($notice)
|
function handle($notice)
|
||||||
{
|
{
|
||||||
if ($this->is_remote($notice)) {
|
if ($this->is_remote($notice)) {
|
||||||
$this->log(LOG_DEBUG, 'Ignoring remote notice ' . $notice->id);
|
common_log(LOG_DEBUG, 'Ignoring remote notice ' . $notice->id);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
require_once(INSTALLDIR.'/lib/omb.php');
|
require_once(INSTALLDIR.'/lib/omb.php');
|
||||||
|
@ -38,7 +38,7 @@ class PublicQueueHandler extends QueueHandler
|
|||||||
try {
|
try {
|
||||||
return jabber_public_notice($notice);
|
return jabber_public_notice($notice);
|
||||||
} catch (XMPPHP_Exception $e) {
|
} catch (XMPPHP_Exception $e) {
|
||||||
$this->log(LOG_ERR, "Got an XMPPHP_Exception: " . $e->getMessage());
|
common_log(LOG_ERR, "Got an XMPPHP_Exception: " . $e->getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,8 @@ class Router
|
|||||||
|
|
||||||
if (Event::handle('StartInitializeRouter', array(&$m))) {
|
if (Event::handle('StartInitializeRouter', array(&$m))) {
|
||||||
|
|
||||||
|
$m->connect('robots.txt', array('action' => 'robotstxt'));
|
||||||
|
|
||||||
$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',
|
||||||
@ -649,7 +651,16 @@ class Router
|
|||||||
|
|
||||||
if (common_config('singleuser', 'enabled')) {
|
if (common_config('singleuser', 'enabled')) {
|
||||||
|
|
||||||
$nickname = common_config('singleuser', 'nickname');
|
$user = User::siteOwner();
|
||||||
|
|
||||||
|
if (!empty($user)) {
|
||||||
|
$nickname = $user->nickname;
|
||||||
|
} else {
|
||||||
|
$nickname = common_config('singleuser', 'nickname');
|
||||||
|
if (empty($nickname)) {
|
||||||
|
throw new ServerException(_("No single user defined for single-user mode."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (array('subscriptions', 'subscribers',
|
foreach (array('subscriptions', 'subscribers',
|
||||||
'all', 'foaf', 'xrds',
|
'all', 'foaf', 'xrds',
|
||||||
@ -697,6 +708,10 @@ class Router
|
|||||||
'nickname' => $nickname),
|
'nickname' => $nickname),
|
||||||
array('tag' => '[a-zA-Z0-9]+'));
|
array('tag' => '[a-zA-Z0-9]+'));
|
||||||
|
|
||||||
|
$m->connect('rsd.xml',
|
||||||
|
array('action' => 'rsd',
|
||||||
|
'nickname' => $nickname));
|
||||||
|
|
||||||
$m->connect('',
|
$m->connect('',
|
||||||
array('action' => 'showstream',
|
array('action' => 'showstream',
|
||||||
'nickname' => $nickname));
|
'nickname' => $nickname));
|
||||||
@ -711,6 +726,7 @@ class Router
|
|||||||
$m->connect('featured', array('action' => 'featured'));
|
$m->connect('featured', array('action' => 'featured'));
|
||||||
$m->connect('favorited/', array('action' => 'favorited'));
|
$m->connect('favorited/', array('action' => 'favorited'));
|
||||||
$m->connect('favorited', array('action' => 'favorited'));
|
$m->connect('favorited', array('action' => 'favorited'));
|
||||||
|
$m->connect('rsd.xml', array('action' => 'rsd'));
|
||||||
|
|
||||||
foreach (array('subscriptions', 'subscribers',
|
foreach (array('subscriptions', 'subscribers',
|
||||||
'nudge', 'all', 'foaf', 'xrds',
|
'nudge', 'all', 'foaf', 'xrds',
|
||||||
@ -758,6 +774,10 @@ class Router
|
|||||||
array('nickname' => '[a-zA-Z0-9]{1,64}'),
|
array('nickname' => '[a-zA-Z0-9]{1,64}'),
|
||||||
array('tag' => '[a-zA-Z0-9]+'));
|
array('tag' => '[a-zA-Z0-9]+'));
|
||||||
|
|
||||||
|
$m->connect(':nickname/rsd.xml',
|
||||||
|
array('action' => 'rsd'),
|
||||||
|
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
||||||
|
|
||||||
$m->connect(':nickname',
|
$m->connect(':nickname',
|
||||||
array('action' => 'showstream'),
|
array('action' => 'showstream'),
|
||||||
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
array('nickname' => '[a-zA-Z0-9]{1,64}'));
|
||||||
|
@ -77,14 +77,12 @@ class Schema
|
|||||||
{
|
{
|
||||||
$type = common_config('db', 'type');
|
$type = common_config('db', 'type');
|
||||||
if (empty(self::$_single)) {
|
if (empty(self::$_single)) {
|
||||||
include "lib/schema.{$type}.php";
|
$schemaClass = ucfirst($type).'Schema';
|
||||||
$class = $type.='Schema';
|
self::$_single = new $schemaClass();
|
||||||
self::$_single = new $class();
|
|
||||||
}
|
}
|
||||||
return self::$_single;
|
return self::$_single;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a ColumnDef object for a single column.
|
* Gets a ColumnDef object for a single column.
|
||||||
*
|
*
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
require_once 'Stomp.php';
|
require_once 'Stomp.php';
|
||||||
require_once 'Stomp/Exception.php';
|
require_once 'Stomp/Exception.php';
|
||||||
|
|
||||||
|
|
||||||
class StompQueueManager extends QueueManager
|
class StompQueueManager extends QueueManager
|
||||||
{
|
{
|
||||||
protected $servers;
|
protected $servers;
|
||||||
@ -587,7 +586,15 @@ class StompQueueManager extends QueueManager
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$ok = $handler->handle($item);
|
// If there's an exception when handling,
|
||||||
|
// log the error and let it get requeued.
|
||||||
|
|
||||||
|
try {
|
||||||
|
$ok = $handler->handle($item);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->_log(LOG_ERR, "Exception on queue $queue: " . $e->getMessage());
|
||||||
|
$ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!$ok) {
|
if (!$ok) {
|
||||||
$this->_log(LOG_WARNING, "Failed handling $info");
|
$this->_log(LOG_WARNING, "Failed handling $info");
|
||||||
|
@ -71,7 +71,7 @@ class GeonamesPlugin extends Plugin
|
|||||||
$loc = $this->getCache(array('name' => $name,
|
$loc = $this->getCache(array('name' => $name,
|
||||||
'language' => $language));
|
'language' => $language));
|
||||||
|
|
||||||
if (!empty($loc)) {
|
if ($loc !== false) {
|
||||||
$location = $loc;
|
$location = $loc;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -87,12 +87,20 @@ class GeonamesPlugin extends Plugin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count($geonames) == 0) {
|
||||||
|
// no results
|
||||||
|
$this->setCache(array('name' => $name,
|
||||||
|
'language' => $language),
|
||||||
|
null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$n = $geonames[0];
|
$n = $geonames[0];
|
||||||
|
|
||||||
$location = new Location();
|
$location = new Location();
|
||||||
|
|
||||||
$location->lat = (string)$n->lat;
|
$location->lat = $this->canonical($n->lat);
|
||||||
$location->lon = (string)$n->lng;
|
$location->lon = $this->canonical($n->lng);
|
||||||
$location->names[$language] = (string)$n->name;
|
$location->names[$language] = (string)$n->name;
|
||||||
$location->location_id = (string)$n->geonameId;
|
$location->location_id = (string)$n->geonameId;
|
||||||
$location->location_ns = self::LOCATION_NS;
|
$location->location_ns = self::LOCATION_NS;
|
||||||
@ -125,7 +133,7 @@ class GeonamesPlugin extends Plugin
|
|||||||
|
|
||||||
$loc = $this->getCache(array('id' => $id));
|
$loc = $this->getCache(array('id' => $id));
|
||||||
|
|
||||||
if (!empty($loc)) {
|
if ($loc !== false) {
|
||||||
$location = $loc;
|
$location = $loc;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -157,8 +165,9 @@ class GeonamesPlugin extends Plugin
|
|||||||
|
|
||||||
$location->location_id = (string)$last->geonameId;
|
$location->location_id = (string)$last->geonameId;
|
||||||
$location->location_ns = self::LOCATION_NS;
|
$location->location_ns = self::LOCATION_NS;
|
||||||
$location->lat = (string)$last->lat;
|
$location->lat = $this->canonical($last->lat);
|
||||||
$location->lon = (string)$last->lng;
|
$location->lon = $this->canonical($last->lng);
|
||||||
|
|
||||||
$location->names[$language] = implode(', ', array_reverse($parts));
|
$location->names[$language] = implode(', ', array_reverse($parts));
|
||||||
|
|
||||||
$this->setCache(array('id' => (string)$last->geonameId),
|
$this->setCache(array('id' => (string)$last->geonameId),
|
||||||
@ -186,13 +195,15 @@ class GeonamesPlugin extends Plugin
|
|||||||
|
|
||||||
function onLocationFromLatLon($lat, $lon, $language, &$location)
|
function onLocationFromLatLon($lat, $lon, $language, &$location)
|
||||||
{
|
{
|
||||||
$lat = rtrim($lat, "0");
|
// Make sure they're canonical
|
||||||
$lon = rtrim($lon, "0");
|
|
||||||
|
$lat = $this->canonical($lat);
|
||||||
|
$lon = $this->canonical($lon);
|
||||||
|
|
||||||
$loc = $this->getCache(array('lat' => $lat,
|
$loc = $this->getCache(array('lat' => $lat,
|
||||||
'lon' => $lon));
|
'lon' => $lon));
|
||||||
|
|
||||||
if (!empty($loc)) {
|
if ($loc !== false) {
|
||||||
$location = $loc;
|
$location = $loc;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -207,6 +218,14 @@ class GeonamesPlugin extends Plugin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count($geonames) == 0) {
|
||||||
|
// no results
|
||||||
|
$this->setCache(array('lat' => $lat,
|
||||||
|
'lon' => $lon),
|
||||||
|
null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$n = $geonames[0];
|
$n = $geonames[0];
|
||||||
|
|
||||||
$parts = array();
|
$parts = array();
|
||||||
@ -225,8 +244,8 @@ class GeonamesPlugin extends Plugin
|
|||||||
|
|
||||||
$location->location_id = (string)$n->geonameId;
|
$location->location_id = (string)$n->geonameId;
|
||||||
$location->location_ns = self::LOCATION_NS;
|
$location->location_ns = self::LOCATION_NS;
|
||||||
$location->lat = (string)$lat;
|
$location->lat = $this->canonical($n->lat);
|
||||||
$location->lon = (string)$lon;
|
$location->lon = $this->canonical($n->lng);
|
||||||
|
|
||||||
$location->names[$language] = implode(', ', $parts);
|
$location->names[$language] = implode(', ', $parts);
|
||||||
|
|
||||||
@ -264,7 +283,7 @@ class GeonamesPlugin extends Plugin
|
|||||||
$n = $this->getCache(array('id' => $id,
|
$n = $this->getCache(array('id' => $id,
|
||||||
'language' => $language));
|
'language' => $language));
|
||||||
|
|
||||||
if (!empty($n)) {
|
if ($n !== false) {
|
||||||
$name = $n;
|
$name = $n;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -278,6 +297,13 @@ class GeonamesPlugin extends Plugin
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count($geonames) == 0) {
|
||||||
|
$this->setCache(array('id' => $id,
|
||||||
|
'language' => $language),
|
||||||
|
null);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$parts = array();
|
$parts = array();
|
||||||
|
|
||||||
foreach ($geonames as $level) {
|
foreach ($geonames as $level) {
|
||||||
@ -412,17 +438,29 @@ class GeonamesPlugin extends Plugin
|
|||||||
throw new Exception("HTTP error code " . $result->code);
|
throw new Exception("HTTP error code " . $result->code);
|
||||||
}
|
}
|
||||||
|
|
||||||
$document = new SimpleXMLElement($result->getBody());
|
$body = $result->getBody();
|
||||||
|
|
||||||
if (empty($document)) {
|
if (empty($body)) {
|
||||||
throw new Exception("No results in response");
|
throw new Exception("Empty HTTP body in response");
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will throw an exception if the XML is mal-formed
|
||||||
|
|
||||||
|
$document = new SimpleXMLElement($body);
|
||||||
|
|
||||||
|
// No children, usually no results
|
||||||
|
|
||||||
|
$children = $document->children();
|
||||||
|
|
||||||
|
if (count($children) == 0) {
|
||||||
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($document->status)) {
|
if (isset($document->status)) {
|
||||||
throw new Exception("Error #".$document->status['value']." ('".$document->status['message']."')");
|
throw new Exception("Error #".$document->status['value']." ('".$document->status['message']."')");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Array of elements
|
// Array of elements, >0 elements
|
||||||
|
|
||||||
return $document->geoname;
|
return $document->geoname;
|
||||||
}
|
}
|
||||||
@ -438,4 +476,12 @@ class GeonamesPlugin extends Plugin
|
|||||||
'names for locations based on user-provided lat/long pairs.'));
|
'names for locations based on user-provided lat/long pairs.'));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function canonical($coord)
|
||||||
|
{
|
||||||
|
$coord = rtrim($coord, "0");
|
||||||
|
$coord = rtrim($coord, ".");
|
||||||
|
|
||||||
|
return $coord;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
92
plugins/UserLimitPlugin.php
Normal file
92
plugins/UserLimitPlugin.php
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* StatusNet, the distributed open-source microblogging tool
|
||||||
|
*
|
||||||
|
* Plugin to limit number of users that can register (best for cloud providers)
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* LICENCE: This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @category Action
|
||||||
|
* @package StatusNet
|
||||||
|
* @author Evan Prodromou <evan@status.net>
|
||||||
|
* @copyright 2009 StatusNet Inc.
|
||||||
|
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
|
||||||
|
* @link http://status.net/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('STATUSNET')) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin to limit number of users that can register (best for cloud providers)
|
||||||
|
*
|
||||||
|
* For cloud providers whose freemium model is based on how many
|
||||||
|
* users can register. We use it on the StatusNet Cloud.
|
||||||
|
*
|
||||||
|
* @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 UserLimitPlugin extends Plugin
|
||||||
|
{
|
||||||
|
public $maxUsers = null;
|
||||||
|
|
||||||
|
function onStartUserRegister(&$user, &$profile)
|
||||||
|
{
|
||||||
|
$this->_checkMaxUsers();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onStartRegistrationTry($action)
|
||||||
|
{
|
||||||
|
$this->_checkMaxUsers();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _checkMaxUsers()
|
||||||
|
{
|
||||||
|
if (!is_null($this->maxUsers)) {
|
||||||
|
|
||||||
|
$cls = new User();
|
||||||
|
|
||||||
|
$cnt = $cls->count();
|
||||||
|
|
||||||
|
if ($cnt >= $this->maxUsers) {
|
||||||
|
$msg = sprintf(_('Cannot register; maximum number of users (%d) reached.'),
|
||||||
|
$this->maxUsers);
|
||||||
|
|
||||||
|
throw new ClientException($msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPluginVersion(&$versions)
|
||||||
|
{
|
||||||
|
$versions[] = array('name' => 'UserLimit',
|
||||||
|
'version' => STATUSNET_VERSION,
|
||||||
|
'author' => 'Evan Prodromou',
|
||||||
|
'homepage' => 'http://status.net/wiki/Plugin:UserLimit',
|
||||||
|
'description' =>
|
||||||
|
_m('Limit the number of users who can register.'));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# live fast! die young!
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
source /etc/statusnet/setup.cfg
|
source /etc/statusnet/setup.cfg
|
||||||
|
|
||||||
export nickname=$1
|
export nickname=$1
|
||||||
|
@ -109,7 +109,13 @@ class QueueDaemon extends SpawningDaemon
|
|||||||
|
|
||||||
$master = new QueueMaster($this->get_id());
|
$master = new QueueMaster($this->get_id());
|
||||||
$master->init($this->all);
|
$master->init($this->all);
|
||||||
$master->service();
|
try {
|
||||||
|
$master->service();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
common_log(LOG_ERR, "Unhandled exception: " . $e->getMessage() . ' ' .
|
||||||
|
str_replace("\n", " ", $e->getTraceAsString()));
|
||||||
|
return self::EXIT_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
$this->log(LOG_INFO, 'finished servicing the queue');
|
$this->log(LOG_INFO, 'finished servicing the queue');
|
||||||
|
|
||||||
|
84
scripts/settag.php
Normal file
84
scripts/settag.php
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* StatusNet - a distributed open-source microblogging tool
|
||||||
|
* Copyright (C) 2008, 2009, 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__) . '/..'));
|
||||||
|
|
||||||
|
$shortoptions = 'd';
|
||||||
|
$longoptions = array('delete');
|
||||||
|
|
||||||
|
$helptext = <<<END_OF_SETTAG_HELP
|
||||||
|
settag.php [options] <site> <tag>
|
||||||
|
Set the tag <tag> for site <site>.
|
||||||
|
|
||||||
|
With -d, delete the tag.
|
||||||
|
|
||||||
|
END_OF_SETTAG_HELP;
|
||||||
|
|
||||||
|
require_once INSTALLDIR.'/scripts/commandline.inc';
|
||||||
|
|
||||||
|
if (count($args) != 2) {
|
||||||
|
show_help();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$nickname = $args[0];
|
||||||
|
$tag = strtolower($args[1]);
|
||||||
|
|
||||||
|
$sn = Status_network::memGet('nickname', $nickname);
|
||||||
|
|
||||||
|
if (empty($sn)) {
|
||||||
|
print "No such site.\n";
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tags = $sn->getTags();
|
||||||
|
|
||||||
|
$i = array_search($tag, $tags);
|
||||||
|
|
||||||
|
if ($i !== false) {
|
||||||
|
if (have_option('d', 'delete')) { // Delete
|
||||||
|
unset($tags[$i]);
|
||||||
|
|
||||||
|
$orig = clone($sn);
|
||||||
|
$sn->tags = implode('|', $tags);
|
||||||
|
$result = $sn->update($orig);
|
||||||
|
if (!$result) {
|
||||||
|
print "Couldn't update.\n";
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print "Already set.\n";
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (have_option('d', 'delete')) { // Delete
|
||||||
|
print "No such tag.\n";
|
||||||
|
exit(-1);
|
||||||
|
} else {
|
||||||
|
$tags[] = $tag;
|
||||||
|
$orig = clone($sn);
|
||||||
|
$sn->tags = implode('|', $tags);
|
||||||
|
$result = $sn->update($orig);
|
||||||
|
if (!$result) {
|
||||||
|
print "Couldn't update.\n";
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# live fast! die young!
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
source /etc/statusnet/setup.cfg
|
source /etc/statusnet/setup.cfg
|
||||||
|
|
||||||
# setup_status_net.sh mysite 'My Site' '1user' 'owner@example.com' 'Firsty McLastname'
|
# setup_status_net.sh mysite 'My Site' '1user' 'owner@example.com' 'Firsty McLastname'
|
||||||
|
Loading…
Reference in New Issue
Block a user