Commit 057ec1fc authored by Craig Andrews's avatar Craig Andrews

Merge branch '0.9.x' into 1.0.x

Conflicts:
	EVENTS.txt
	lib/imqueuehandler.php
	lib/jabber.php
	lib/util.php
	plugins/Xmpp/Sharing_XMPP.php
parents d1465170 f60f2c52
......@@ -717,3 +717,17 @@ SendImConfirmationCode: Send a confirmation code to confirm a user owns an IM sc
- $screenname: screenname being confirmed
- $code: confirmation code for confirmation URL
- $user: user requesting the confirmation
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
......@@ -2,8 +2,8 @@
README
------
StatusNet 0.9.0 ("Stand") Beta 3
20 Jan 2010
StatusNet 0.9.0 ("Stand") Beta 5
1 Feb 2010
This is the README file for StatusNet (formerly Laconica), the Open
Source microblogging platform. It includes installation instructions,
......@@ -78,6 +78,11 @@ New this version
================
This is a major feature release since version 0.8.2, released Nov 1 2009.
It is also a security release since 0.9.0beta4 January 27 2010. Beta
users are strongly encouraged to upgrade to deal with a security alert.
http://status.net/wiki/Security_alert_0000002
Notable changes this version:
- Records of deleted notices are stored without the notice content.
......@@ -198,6 +203,77 @@ Notable changes this version:
- Major refactoring of queue handlers to manage very
large hosting site (like status.net)
- SubscriptionThrottle plugin to prevent subscription spamming
- Don't enqueue into plugin or SMS queues when disabled (breaks unqueuehandler if SMS queue isn't attached)
- Improve name validation checks on local File references
- fix local file include vulnerability in doc.php
- Reusing fixed selector name for 'processing' in util.js
- Removed hAtom pattern from registration page.
- restructuring of User::registerNew() lost password munging
- Add a script to clear the cache for a given key
- buggy fetch for site owner
- Added missing concat of </li> in Realtime response
- Updated XHR binded events to work better in jQuery 1.4.1. Using .live() for event delegation instead of jQuery.data() and checking to see if an element was previously binded.
- Updated jQuery Form Plugin from v2.17 to v2.36
- Updated jQuery JavaScript Library from v1.3.2 to v1.4.1
- move schema.type.php to typeschema.php like other files
- Add Really Simple Discovery (RSD) support
- Add a robots.txt URL to the site root
- error clearing tags for profiles from memcached
- on exceptions, stomp logs the error and reenqueues
- add lat, lon, location and remove closing tag from geocode.php
- Use passed-in lat long in geocode.php
- better handling of null responses from geonames.org
- Globalized form notice data geo values
- Using jQuery chaining in FormNoticeXHR
- Using form object instead of form_id and find(). Slightly faster and easier to read.
- removed describeTable from base class, and fixed it up in pgsql
- getTableDef() mostly working in postgres
- move the schema DDL sql off into seperate files for each db we support
- plugin to limit number of registered users
- add hooks for user registration
- live fast, die young in bash scripts
- for single-user mode, retrieve either site owner or defined nickname
- method to get the site owner
- define a constant for the 'owner' role of a site
- add simple cache getter/setter static functions to Memcached_DataObject
- Adds notice author's name to @title in Realtime response
- Hides .author from XHR response in showstream
- Hides .author from XHR response in showstream
- Fix more fatal errors in queue edge cases
- Don't attempt to resend XMPP messages that can't be broadcast due to the profile being deleted.
- Wrap each bit of distrib queue handler's saving operation in a try/catch; log exceptions but let everything else continue.
- Log exceptions from queuedaemon.php if they're not already caught
- Move sessions settings to its own panel
- Fixes for status_network db object .ini and tag setter script
- Add a script to set tags for sites
- Adjust API authentication to also check for OAuth protocol params in the HTTP Authorization header, as defined in OAuth HTTP Authorization Scheme.
- Last-chance distribution if enqueueing fails
- Manual failover for stomp queues.
- lost config in index.php made all traffic go to master
- "Revert "move RW setup above user get in index.php so remember_me works""
- Revert "move RW setup above user get in index.php so remember_me works"
- move RW setup above user get in index.php so remember_me works
- hide most DB_DataObject errors
- always set up database_rw, regardless, so cached sessions work
- update mysqltimestamps on insert and update
- additional debugging data for Sessions
- 'Sign in with Twitter' button img
- Update to biz theme
- Remove redundant session token field from form (was already being added by base class).
- 'Sign in with Twitter' button img
- Can now set $config['queue']['stomp_persistent'] = false; to explicitly disable persistence when we queue items
- Showing processing indicator for form_repeat on submit instead of form
- Removed avatar from repeat of username (matches noticelist)
- Removed unused variable assignment for avatar URL and added missing fn
- Don't preemptively close existing DB connections for web views (needed to keep # of conns from going insane on multi-site queue daemons, so just doing for CLI) May, or may not, help with mystery session problems
- dropping the setcookie() call from common_ensure_session() since we're pretty sure it's unnecessary
- append '/' on cookie path for now (may still need some refactoring)
- set session cookie correctly
- Fix for Mapstraction plugin's zoomed map links
- debug log line for control channel sub
- Move faceboookapp.js to the Facebook plugin
- fix for fix for bad realtime JS load
- default 24-hour expiry on Memcached objects where not specified.
Prerequisites
=============
......@@ -597,26 +673,19 @@ server is probably a good idea for high-volume sites.
needs as a parameter the install path; if you run it from the
StatusNet dir, "." should suffice.
This will run eight (for now) queue handlers:
This will run the queue handlers:
* queuedaemon.php - polls for queued items for inbox processing and
pushing out to OMB, SMS, XMPP, etc.
* xmppdaemon.php - listens for new XMPP messages from users and stores
them as notices in the database.
* jabberqueuehandler.php - sends queued notices in the database to
registered users who should receive them.
* publicqueuehandler.php - sends queued notices in the database to
public feed listeners.
* ombqueuehandler.php - sends queued notices to OpenMicroBlogging
recipients on foreign servers.
* smsqueuehandler.php - sends queued notices to SMS-over-email addresses
of registered users.
* xmppconfirmhandler.php - sends confirmation messages to registered
users.
Note that these queue daemons are pretty raw, and need your care. In
particular, they leak memory, and you may want to restart them on a
regular (daily or so) basis with a cron job. Also, if they lose
the connection to the XMPP server for too long, they'll simply die. It
may be a good idea to use a daemon-monitoring service, like 'monit',
them as notices in the database; also pulls queued XMPP output from
queuedaemon.php to push out to clients.
These two daemons will automatically restart in most cases of failure
including memory leaks (if a memory_limit is set), but may still die
or behave oddly if they lose connections to the XMPP or queue servers.
It may be a good idea to use a daemon-monitoring service, like 'monit',
to check their status and keep them running.
All the daemons write their process IDs (pids) to /var/run/ by
......@@ -626,7 +695,7 @@ daemons.
Since version 0.8.0, it's now possible to use a STOMP server instead of
our kind of hacky home-grown DB-based queue solution. See the "queues"
config section below for how to configure to use STOMP. As of this
writing, the software has been tested with ActiveMQ (
writing, the software has been tested with ActiveMQ.
Sitemaps
--------
......@@ -712,10 +781,12 @@ subdirectory to add a new language to your system. You'll need to
compile the ".po" files into ".mo" files, however.
Contributions of translation information to StatusNet are very easy:
you can use the Web interface at http://status.net/pootle/ to add one
you can use the Web interface at TranslateWiki.net to add one
or a few or lots of new translations -- or even new languages. You can
also download more up-to-date .po files there, if you so desire.
For info on helping with translations, see http://status.net/wiki/Translations
Backups
-------
......@@ -1501,6 +1572,20 @@ 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.
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
=======
......
......@@ -67,8 +67,6 @@ class ApiOauthAuthorizeAction extends ApiOauthAction
{
parent::prepare($args);
common_debug("apioauthauthorize");
$this->nickname = $this->trimmed('nickname');
$this->password = $this->arg('password');
$this->oauth_token = $this->arg('oauth_token');
......@@ -99,24 +97,17 @@ class ApiOauthAuthorizeAction extends ApiOauthAction
} else {
// XXX: make better error messages
if (empty($this->oauth_token)) {
common_debug("No request token found.");
$this->clientError(_('Bad request.'));
$this->clientError(_('No oauth_token parameter provided.'));
return;
}
if (empty($this->app)) {
common_debug('No app for that token.');
$this->clientError(_('Bad request.'));
$this->clientError(_('Invalid token.'));
return;
}
$name = $this->app->name;
common_debug("Requesting auth for app: " . $name);
$this->showForm();
}
......@@ -124,8 +115,6 @@ class ApiOauthAuthorizeAction extends ApiOauthAction
function handlePost()
{
common_debug("handlePost()");
// check session token for CSRF protection.
$token = $this->trimmed('token');
......@@ -202,21 +191,15 @@ class ApiOauthAuthorizeAction extends ApiOauthAction
// A callback specified in the app setup overrides whatever
// is passed in with the request.
common_debug("Req token is authorized - doing callback");
if (!empty($this->app->callback_url)) {
$this->callback = $this->app->callback_url;
}
if (!empty($this->callback)) {
// XXX: Need better way to build this redirect url.
$target_url = $this->getCallback($this->callback,
array('oauth_token' => $this->oauth_token));
common_debug("Doing callback to $target_url");
common_redirect($target_url, 303);
} else {
common_debug("callback was empty!");
......@@ -236,9 +219,12 @@ class ApiOauthAuthorizeAction extends ApiOauthAction
} else if ($this->arg('deny')) {
$datastore = new ApiStatusNetOAuthDataStore();
$datastore->revoke_token($this->oauth_token, 0);
$this->elementStart('p');
$this->raw(sprintf(_("The request token %s has been denied."),
$this->raw(sprintf(_("The request token %s has been denied and revoked."),
$this->oauth_token));
$this->elementEnd('p');
......@@ -303,13 +289,17 @@ class ApiOauthAuthorizeAction extends ApiOauthAction
$access = ($this->app->access_type & Oauth_application::$writeAccess) ?
'access and update' : 'access';
$msg = _("The application <strong>%1$s</strong> by <strong>%2$s</strong> would like " .
"the ability to <strong>%3$s</strong> your account data.");
$msg = _('The application <strong>%1$s</strong> by ' .
'<strong>%2$s</strong> would like the ability ' .
'to <strong>%3$s</strong> your %4$s account data. ' .
'You should only give access to your %4$s account ' .
'to third parties you trust.');
$this->raw(sprintf($msg,
$this->app->name,
$this->app->organization,
$access));
$access,
common_config('site', 'name')));
$this->elementEnd('p');
$this->elementEnd('li');
$this->elementEnd('ul');
......@@ -371,6 +361,31 @@ class ApiOauthAuthorizeAction extends ApiOauthAction
function showLocalNav()
{
// NOP
}
/**
* Show site notice.
*
* @return nothing
*/
function showSiteNotice()
{
// NOP
}
/**
* Show notice form.
*
* Show the form for posting a new notice
*
* @return nothing
*/
function showNoticeForm()
{
// NOP
}
}
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Action class to delete an OAuth application
*
* 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 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') && !defined('LACONICA')) {
exit(1);
}
/**
* Delete an OAuth appliction
*
* @category Action
* @package StatusNet
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*/
class DeleteapplicationAction extends Action
{
var $app = null;
/**
* Take arguments for running
*
* @param array $args $_REQUEST args
*
* @return boolean success flag
*/
function prepare($args)
{
if (!parent::prepare($args)) {
return false;
}
if (!common_logged_in()) {
$this->clientError(_('You must be logged in to delete an application.'));
return false;
}
$id = (int)$this->arg('id');
$this->app = Oauth_application::staticGet('id', $id);
if (empty($this->app)) {
$this->clientError(_('Application not found.'));
return false;
}
$cur = common_current_user();
if ($cur->id != $this->app->owner) {
$this->clientError(_('You are not the owner of this application.'), 401);
return false;
}
return true;
}
/**
* Handle request
*
* Shows a page with list of favorite notices
*
* @param array $args $_REQUEST args; handled in prepare()
*
* @return void
*/
function handle($args)
{
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
$this->clientError(_('There was a problem with your session token.'));
return;
}
if ($this->arg('no')) {
common_redirect(common_local_url('showapplication',
array('id' => $this->app->id)), 303);
} elseif ($this->arg('yes')) {
$this->handlePost();
common_redirect(common_local_url('oauthappssettings'), 303);
} else {
$this->showPage();
}
}
}
function showContent() {
$this->areYouSureForm();
}
function title() {
return _('Delete application');
}
function showNoticeForm() {
// nop
}
/**
* Confirm with user.
*
* Shows a confirmation form.
*
* @return void
*/
function areYouSureForm()
{
$id = $this->app->id;
$this->elementStart('form', array('id' => 'deleteapplication-' . $id,
'method' => 'post',
'class' => 'form_settings form_entity_block',
'action' => common_local_url('deleteapplication',
array('id' => $this->app->id))));
$this->elementStart('fieldset');
$this->hidden('token', common_session_token());
$this->element('legend', _('Delete application'));
$this->element('p', null,
_('Are you sure you want to delete this application? '.
'This will clear all data about the application from the '.
'database, including all existing user connections.'));
$this->submit('form_action-no',
_('No'),
'submit form_action-primary',
'no',
_("Do not delete this application"));
$this->submit('form_action-yes',
_('Yes'),
'submit form_action-secondary',
'yes', _('Delete this application'));
$this->elementEnd('fieldset');
$this->elementEnd('form');
}
/**
* Actually delete the app
*
* @return void
*/
function handlePost()
{
$this->app->delete();
}
}
......@@ -54,6 +54,9 @@ class DocAction extends Action
parent::prepare($args);
$this->title = $this->trimmed('title');
if (!preg_match('/^[a-zA-Z0-9_-]*$/', $this->title)) {
$this->title = 'help';
}
$this->output = null;
$this->loadDoc();
......
......@@ -179,6 +179,9 @@ class EditApplicationAction extends OwnerDesignAction
} elseif (mb_strlen($name) > 255) {
$this->showForm(_('Name is too long (max 255 chars).'));
return;
} else if ($this->nameExists($name)) {
$this->showForm(_('Name already in use. Try another one.'));
return;
} elseif (empty($description)) {
$this->showForm(_('Description is required.'));
return;
......@@ -260,5 +263,26 @@ class EditApplicationAction extends OwnerDesignAction
common_redirect(common_local_url('oauthappssettings'), 303);
}
/**
* Does the app name already exist?
*
* Checks the DB to see someone has already registered and app
* with the same name.
*
* @param string $name app name to check
*
* @return boolean true if the name already exists
*/
function nameExists($name)
{
$newapp = Oauth_application::staticGet('name', $name);
if (!$newapp) {
return false;
} else {
return $newapp->id != $this->app->id;
}
}
}
......@@ -42,6 +42,10 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
*/
class GeocodeAction extends Action
{
var $lat = null;
var $lon = null;
var $location = null;
function prepare($args)
{
parent::prepare($args);
......@@ -52,12 +56,7 @@ class GeocodeAction extends Action
}
$this->lat = $this->trimmed('lat');
$this->lon = $this->trimmed('lon');
$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;
}
$this->location = Location::fromLatLon($this->lat, $this->lon);
return true;
}
......@@ -95,4 +94,3 @@ class GeocodeAction extends Action
return true;
}
}
?>
......@@ -71,7 +71,7 @@ class GetfileAction extends Action
$filename = $this->trimmed('filename');
$path = null;
if ($filename) {
if ($filename && File::validFilename($filename)) {
$path = File::path($filename);
}
......
......@@ -158,6 +158,9 @@ class NewApplicationAction extends OwnerDesignAction
if (empty($name)) {
$this->showForm(_('Name is required.'));
return;
} else if ($this->nameExists($name)) {
$this->showForm(_('Name already in use. Try another one.'));
return;
} elseif (mb_strlen($name) > 255) {
$this->showForm(_('Name is too long (max 255 chars).'));
return;
......@@ -273,5 +276,22 @@ class NewApplicationAction extends OwnerDesignAction
}
/**
* Does the app name already exist?
*
* Checks the DB to see someone has already registered and app
* with the same name.
*
* @param string $name app name to check
*
* @return boolean true if the name already exists
*/
function nameExists($name)
{
$app = Oauth_application::staticGet('name', $name);
return ($app !== false);
}
}
......@@ -33,6 +33,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
require_once INSTALLDIR . '/lib/connectsettingsaction.php';
require_once INSTALLDIR . '/lib/applicationlist.php';
require_once INSTALLDIR . '/lib/apioauthstore.php';
/**
* Show connected OAuth applications
......@@ -71,11 +72,6 @@ class OauthconnectionssettingsAction extends ConnectSettingsAction
return _('Connected applications');
}
function isReadOnly($args)
{
return true;
}
/**
* Instructions for use
*
......@@ -153,6 +149,13 @@ class OauthconnectionssettingsAction extends ConnectSettingsAction
}
}
/**
* Revoke access to an authorized OAuth application
*
* @param int $appId the ID of the application
*
*/
function revokeAccess($appId)
{
$cur = common_current_user();
......@@ -164,6 +167,8 @@ class OauthconnectionssettingsAction extends ConnectSettingsAction
return false;
}
// XXX: Transaction here?