Merge branch 'master' of git://gitorious.org/statusnet/mainline

This commit is contained in:
Ian Denhardt 2010-08-02 11:10:19 -04:00
commit 762731d8ee
337 changed files with 30136 additions and 17820 deletions

View File

@ -141,7 +141,7 @@ StartLogout: Before logging out
EndLogout: After logging out EndLogout: After logging out
- $action: the logout action - $action: the logout action
ArgsInitialized: After the argument array has been initialized ArgsInitialize: After the argument array has been initialized
- $args: associative array of arguments, can be modified - $args: associative array of arguments, can be modified
StartAddressData: Allows the site owner to provide additional information about themselves for contact (e.g., tagline, email, location) StartAddressData: Allows the site owner to provide additional information about themselves for contact (e.g., tagline, email, location)

53
README
View File

@ -2,8 +2,8 @@
README README
------ ------
StatusNet 0.9.2 ("King of Birds") StatusNet 0.9.3 ("Half a World Away")
3 May 2010 29 June 2010
This is the README file for StatusNet, the Open Source microblogging This is the README file for StatusNet, the Open Source microblogging
platform. It includes installation instructions, descriptions of platform. It includes installation instructions, descriptions of
@ -77,40 +77,27 @@ for additional terms.
New this version New this version
================ ================
This is a minor bug and feature release since version 0.9.1 released 28 This is a minor bug and feature release since version 0.9.2 released on
March 2010. 4 May 2010.
Because of fixes to OStatus bugs, it is highly recommended that all For best compatibility with client software and site federation, and a lot of
public sites upgrade to the new version immediately. bug fixes, it is highly recommended that all public sites upgrade to the new
version.
Notable changes this version: Notable changes this version:
- Installer no longer fails with a PHP fatal error when trying to set up the - Enhanced API output to aid StatusNet-specific clients
subscription to update@status.net - Many updates to user interface translation from TranslateWiki
- Fixed email notifications for @-replies that come in via OStatus - OStatus now works subscribing to SSL-protected sites by default
- OStatus related Fixes to the cloudy theme - OpenID now works on PHP 5.3, supports closer site integration.
- Pass geo locations over Twitter bridge (will only be used if enabled on the - Numerous API and FOAF output fixes.
Twitter side) - Fixes to Facebook integration for FB API behavior changes
- scripts/showplugins.php - script to dump the list of activated plugins and - PostgreSQL support updates
their settings - Initial version of a custom theme uploader (disabled by default)
- scripts/fixup_blocks.php - script to finds any stray subscriptions in - LDAP auth plugins cleanup
violation of blocks, and removes them - Many other bugfixes
- Allow blocking someone who's not currently subscribed to you (prevents
seeing @-replies from them, or them subbing to you in future)
- Default 2-second timeout on Geonames web service lookups
- Improved localization for plugins
- New anti-spam measures: added nofollow rels to group members list,
subscribers list
- Shared cache key option for Geonames plugin (lets multi-instance sites
share their cached geoname lookups)
- Stability fixes to the TwitterStatusFetcher
- If user allows location sharing but turned off browser location use profile
location
- Improved group listing via the API
- Improved FOAF output
- Several other bugfixes
A full changelog is available at http://status.net/wiki/StatusNet_0.9.2. A full changelog is available at http://status.net/wiki/StatusNet_0.9.3.
Prerequisites Prerequisites
============= =============
@ -121,8 +108,8 @@ run correctly.
- PHP 5.2.3+. It may be possible to run this software on earlier - PHP 5.2.3+. It may be possible to run this software on earlier
versions of PHP, but many of the functions used are only available versions of PHP, but many of the functions used are only available
in PHP 5.2 or above. 5.2.6 or later is needed for XMPP background in PHP 5.2 or above. 5.2.6 or later is needed for XMPP background
daemons on 64-bit platforms. PHP 5.3.x should work but is known daemons on 64-bit platforms. PHP 5.3.x should work correctly in this
to cause some failures for OpenID. release, but problems with some plugins are possible.
- MySQL 5.x. The StatusNet database is stored, by default, in a MySQL - MySQL 5.x. The StatusNet database is stored, by default, in a MySQL
server. It has been primarily tested on 5.x servers, although it may server. It has been primarily tested on 5.x servers, although it may
be possible to install on earlier (or later!) versions. The server be possible to install on earlier (or later!) versions. The server

View File

@ -18,15 +18,19 @@
* *
* @category Actions * @category Actions
* @package Actions * @package Actions
* @author Evan Prodromou <evan@status.net>
* @author Mike Cochrane <mikec@mikenz.geek.nz>
* @author Robin Millette <millette@controlyourself.ca>
* @author Adrian Lang <mail@adrianlang.de> * @author Adrian Lang <mail@adrianlang.de>
* @author Meitar Moscovitz <meitarm@gmail.com> * @author Brenda Wallace <shiny@cpan.org>
* @author Sarven Capadisli <csarven@status.net> * @author Brion Vibber <brion@pobox.com>
* @author Craig Andrews <candrews@integralblue.com> * @author Craig Andrews <candrews@integralblue.com>
* @author Evan Prodromou <evan@status.net>
* @author Jeffery To <jeffery.to@gmail.com> * @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@controlyourself.ca> * @author Meitar Moscovitz <meitarm@gmail.com>
* @author Mike Cochrane <mikec@mikenz.geek.nz>
* @author Robin Millette <millette@status.net>
* @author Sarven Capadisli <csarven@status.net>
* @author Siebrand Mazeland <s.mazeland@xs4all.nl>
* @author Zach Copley <zach@status.net>
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @license GNU Affero General Public License http://www.gnu.org/licenses/ * @license GNU Affero General Public License http://www.gnu.org/licenses/
* @link http://status.net * @link http://status.net
*/ */
@ -139,10 +143,10 @@ class AllAction extends ProfileAction
$message .= _('Try subscribing to more people, [join a group](%%action.groups%%) or post something yourself.'); $message .= _('Try subscribing to more people, [join a group](%%action.groups%%) or post something yourself.');
} else { } else {
// TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@" // TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@"
$message .= sprintf(_('You can try to [nudge %1$s](../%2$s) from his profile or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname); $message .= sprintf(_('You can try to [nudge %1$s](../%2$s) from their profile or [post something to their attention](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname);
} }
} else { } else {
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname); $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to their attention.'), $this->user->nickname);
} }
$this->elementStart('div', 'guide'); $this->elementStart('div', 'guide');

View File

@ -112,10 +112,12 @@ class AllrssAction extends Rss10Action
$c = array('url' => common_local_url('allrss', $c = array('url' => common_local_url('allrss',
array('nickname' => array('nickname' =>
$user->nickname)), $user->nickname)),
// TRANS: Message is used as link title. %s is a user nickname.
'title' => sprintf(_('%s and friends'), $user->nickname), 'title' => sprintf(_('%s and friends'), $user->nickname),
'link' => common_local_url('all', 'link' => common_local_url('all',
array('nickname' => array('nickname' =>
$user->nickname)), $user->nickname)),
// TRANS: Message is used as link description. %1$s is a username, %2$s is a site name.
'description' => sprintf(_('Updates from %1$s and friends on %2$s!'), 'description' => sprintf(_('Updates from %1$s and friends on %2$s!'),
$user->nickname, common_config('site', 'name'))); $user->nickname, common_config('site', 'name')));
return $c; return $c;

View File

@ -21,8 +21,10 @@
* *
* @category API * @category API
* @package StatusNet * @package StatusNet
* @author Brion Vibber <brion@pobox.com>
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@status.net>
* @author Robin Millette <robin@millette.info> * @author Robin Millette <robin@millette.info>
* @author Siebrand Mazeland <s.mazeland@xs4all.nl>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc. * @copyright 2009 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

View File

@ -21,6 +21,7 @@
* *
* @category API * @category API
* @package StatusNet * @package StatusNet
* @author Siebrand Mazeland <s.mazeland@xs4all.nl>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc. * @copyright 2009 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

View File

@ -22,7 +22,7 @@
* @category API * @category API
* @package StatusNet * @package StatusNet
* @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/
*/ */
@ -131,7 +131,7 @@ class ApiAccountUpdateProfileColorsAction extends ApiAuthAction
try { try {
$this->setColors($design); $this->setColors($design);
} catch (WebColorException $e) { } catch (WebColorException $e) {
$this->clientError($e->getMessage()); $this->clientError($e->getMessage(), 400, $this->format);
return false; return false;
} }
@ -153,7 +153,7 @@ class ApiAccountUpdateProfileColorsAction extends ApiAuthAction
try { try {
$this->setColors($design); $this->setColors($design);
} catch (WebColorException $e) { } catch (WebColorException $e) {
$this->clientError($e->getMessage()); $this->clientError($e->getMessage(), 400, $this->format);
return false; return false;
} }

View File

@ -75,7 +75,7 @@ class ApiAccountVerifyCredentialsAction extends ApiAuthAction
if ($this->format == 'xml') { if ($this->format == 'xml') {
$this->initDocument('xml'); $this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user); $this->showTwitterXmlUser($twitter_user, 'user', true);
$this->endDocument('xml'); $this->endDocument('xml');
} elseif ($this->format == 'json') { } elseif ($this->format == 'json') {
$this->initDocument('json'); $this->initDocument('json');

View File

@ -23,7 +23,7 @@
* @package StatusNet * @package StatusNet
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@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/
*/ */
@ -65,7 +65,7 @@ class ApiBlockCreateAction extends ApiAuthAction
parent::prepare($args); parent::prepare($args);
$this->user = $this->auth_user; $this->user = $this->auth_user;
$this->other = $this->getTargetUser($this->arg('id')); $this->other = $this->getTargetProfile($this->arg('id'));
return true; return true;
} }

View File

@ -23,7 +23,7 @@
* @package StatusNet * @package StatusNet
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@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/
*/ */
@ -64,7 +64,7 @@ class ApiBlockDestroyAction extends ApiAuthAction
parent::prepare($args); parent::prepare($args);
$this->user = $this->auth_user; $this->user = $this->auth_user;
$this->other = $this->getTargetUser($this->arg('id')); $this->other = $this->getTargetProfile($this->arg('id'));
return true; return true;
} }

View File

@ -232,7 +232,8 @@ class ApiDirectMessageAction extends ApiAuthAction
function showXmlDirectMessages() function showXmlDirectMessages()
{ {
$this->initDocument('xml'); $this->initDocument('xml');
$this->elementStart('direct-messages', array('type' => 'array')); $this->elementStart('direct-messages', array('type' => 'array',
'xmlns:statusnet' => 'http://status.net/schema/api/1/'));
foreach ($this->messages as $m) { foreach ($this->messages as $m) {
$dm_array = $this->directMessageArray($m); $dm_array = $this->directMessageArray($m);

View File

@ -25,6 +25,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>
* @copyright 2009 StatusNet, Inc. * @copyright 2009 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -25,6 +25,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>
* @copyright 2009 StatusNet, Inc. * @copyright 2009 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -24,7 +24,7 @@
* @author Dan Moore <dan@moore.cx> * @author Dan Moore <dan@moore.cx>
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@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/
*/ */
@ -67,7 +67,7 @@ class ApiFriendshipsCreateAction extends ApiAuthAction
parent::prepare($args); parent::prepare($args);
$this->user = $this->auth_user; $this->user = $this->auth_user;
$this->other = $this->getTargetUser($id); $this->other = $this->getTargetProfile($this->arg('id'));
return true; return true;
} }
@ -106,7 +106,7 @@ class ApiFriendshipsCreateAction extends ApiAuthAction
if (empty($this->other)) { if (empty($this->other)) {
$this->clientError( $this->clientError(
_('Could not follow user: User not found.'), _('Could not follow user: profile not found.'),
403, 403,
$this->format $this->format
); );

View File

@ -24,7 +24,7 @@
* @author Dan Moore <dan@moore.cx> * @author Dan Moore <dan@moore.cx>
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@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/
*/ */
@ -67,7 +67,7 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction
parent::prepare($args); parent::prepare($args);
$this->user = $this->auth_user; $this->user = $this->auth_user;
$this->other = $this->getTargetUser($id); $this->other = $this->getTargetProfile($this->arg('id'));
return true; return true;
} }
@ -125,8 +125,7 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction
} }
// throws an exception on error // throws an exception on error
Subscription::cancel($this->user->getProfile(), Subscription::cancel($this->user->getProfile(), $this->other);
$this->other->getProfile());
$this->initDocument($this->format); $this->initDocument($this->format);
$this->showProfile($this->other, $this->format); $this->showProfile($this->other, $this->format);

View File

@ -24,7 +24,7 @@
* @author Dan Moore <dan@moore.cx> * @author Dan Moore <dan@moore.cx>
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@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/
*/ */
@ -50,8 +50,8 @@ require_once INSTALLDIR . '/lib/apiprivateauth.php';
class ApiFriendshipsExistsAction extends ApiPrivateAuthAction class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
{ {
var $user_a = null; var $profile_a = null;
var $user_b = null; var $profile_b = null;
/** /**
* Take arguments for running * Take arguments for running
@ -66,11 +66,8 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
{ {
parent::prepare($args); parent::prepare($args);
$user_a_id = $this->trimmed('user_a'); $this->profile_a = $this->getTargetProfile($this->trimmed('user_a'));
$user_b_id = $this->trimmed('user_b'); $this->profile_b = $this->getTargetProfile($this->trimmed('user_b'));
$this->user_a = $this->getTargetUser($user_a_id);
$this->user_b = $this->getTargetUser($user_b_id);
return true; return true;
} }
@ -89,16 +86,16 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
{ {
parent::handle($args); parent::handle($args);
if (empty($this->user_a) || empty($this->user_b)) { if (empty($this->profile_a) || empty($this->profile_b)) {
$this->clientError( $this->clientError(
_('Two user ids or screen_names must be supplied.'), _('Two valid IDs or screen_names must be supplied.'),
400, 400,
$this->format $this->format
); );
return; return;
} }
$result = $this->user_a->isSubscribed($this->user_b); $result = Subscription::exists($this->profile_a, $this->profile_b);
switch ($this->format) { switch ($this->format) {
case 'xml': case 'xml':

View File

@ -26,6 +26,7 @@
* @author Jeffery To <jeffery.to@gmail.com> * @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc. * @copyright 2009 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -26,6 +26,7 @@
* @author Jeffery To <jeffery.to@gmail.com> * @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc. * @copyright 2009 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -26,6 +26,7 @@
* @author Jeffery To <jeffery.to@gmail.com> * @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc. * @copyright 2009 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -26,6 +26,7 @@
* @author Jeffery To <jeffery.to@gmail.com> * @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc. * @copyright 2009 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -26,6 +26,7 @@
* @author Jeffery To <jeffery.to@gmail.com> * @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc. * @copyright 2009 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */
@ -93,6 +94,7 @@ class ApiGroupListAction extends ApiBareAuthAction
parent::handle($args); parent::handle($args);
$sitename = common_config('site', 'name'); $sitename = common_config('site', 'name');
// TRANS: %s is a user name
$title = sprintf(_("%s's groups"), $this->user->nickname); $title = sprintf(_("%s's groups"), $this->user->nickname);
$taguribase = TagURI::base(); $taguribase = TagURI::base();
$id = "tag:$taguribase:Groups"; $id = "tag:$taguribase:Groups";
@ -100,10 +102,12 @@ class ApiGroupListAction extends ApiBareAuthAction
'usergroups', 'usergroups',
array('nickname' => $this->user->nickname) array('nickname' => $this->user->nickname)
); );
$subtitle = sprintf( $subtitle = sprintf(
_("Groups %1\$s is a member of on %2\$s."), // TRANS: Meant to convey the user %2$s is a member of each of the groups listed on site %1$s
$this->user->nickname, _("%1\$s groups %2\$s is a member of."),
$sitename $sitename,
$this->user->nickname
); );
switch($this->format) { switch($this->format) {

View File

@ -26,6 +26,7 @@
* @author Jeffery To <jeffery.to@gmail.com> * @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc. * @copyright 2009 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */
@ -87,6 +88,7 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction
parent::handle($args); parent::handle($args);
$sitename = common_config('site', 'name'); $sitename = common_config('site', 'name');
// TRANS: Message is used as a title. %s is a site name.
$title = sprintf(_("%s groups"), $sitename); $title = sprintf(_("%s groups"), $sitename);
$taguribase = TagURI::base(); $taguribase = TagURI::base();
$id = "tag:$taguribase:Groups"; $id = "tag:$taguribase:Groups";

View File

@ -26,6 +26,7 @@
* @author Jeffery To <jeffery.to@gmail.com> * @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc. * @copyright 2009 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -26,6 +26,7 @@
* @author Jeffery To <jeffery.to@gmail.com> * @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc. * @copyright 2009 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -88,15 +88,15 @@ class ApiMediaUploadAction extends ApiAuthAction
try { try {
$upload = MediaFile::fromUpload('media', $this->auth_user); $upload = MediaFile::fromUpload('media', $this->auth_user);
} catch (ClientException $ce) { } catch (Exception $e) {
$this->clientError($ce->getMessage()); $this->clientError($e->getMessage(), $e->getCode());
return; return;
} }
if (isset($upload)) { if (isset($upload)) {
$this->showResponse($upload); $this->showResponse($upload);
} else { } else {
$this->clientError('Upload failed.'); $this->clientError(_('Upload failed.'));
return; return;
} }
} }

View File

@ -22,7 +22,7 @@
* @category Search * @category Search
* @package StatusNet * @package StatusNet
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@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/
*/ */
@ -31,6 +31,8 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1); exit(1);
} }
require_once INSTALLDIR.'/lib/apiprivateauth.php';
/** /**
* Action for outputting search results in Twitter compatible Atom * Action for outputting search results in Twitter compatible Atom
* format. * format.
@ -44,10 +46,10 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @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/
* *
* @see ApiAction * @see ApiPrivateAuthAction
*/ */
class TwitapisearchatomAction extends ApiAction class ApiSearchAtomAction extends ApiPrivateAuthAction
{ {
var $cnt; var $cnt;
@ -96,8 +98,11 @@ class TwitapisearchatomAction extends ApiAction
function prepare($args) function prepare($args)
{ {
common_debug("in apisearchatom prepare()");
parent::prepare($args); parent::prepare($args);
$this->query = $this->trimmed('q'); $this->query = $this->trimmed('q');
$this->lang = $this->trimmed('lang'); $this->lang = $this->trimmed('lang');
$this->rpp = $this->trimmed('rpp'); $this->rpp = $this->trimmed('rpp');
@ -138,6 +143,7 @@ class TwitapisearchatomAction extends ApiAction
function handle($args) function handle($args)
{ {
parent::handle($args); parent::handle($args);
common_debug("In apisearchatom handle()");
$this->showAtom(); $this->showAtom();
} }

View File

@ -22,7 +22,7 @@
* @category Search * @category Search
* @package StatusNet * @package StatusNet
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@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/
*/ */
@ -31,6 +31,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1); exit(1);
} }
require_once INSTALLDIR.'/lib/apiprivateauth.php';
require_once INSTALLDIR.'/lib/jsonsearchresultslist.php'; require_once INSTALLDIR.'/lib/jsonsearchresultslist.php';
/** /**
@ -44,7 +45,7 @@ require_once INSTALLDIR.'/lib/jsonsearchresultslist.php';
* @see ApiAction * @see ApiAction
*/ */
class TwitapisearchjsonAction extends ApiAction class ApiSearchJSONAction extends ApiPrivateAuthAction
{ {
var $query; var $query;
var $lang; var $lang;
@ -64,6 +65,8 @@ class TwitapisearchjsonAction extends ApiAction
function prepare($args) function prepare($args)
{ {
common_debug("apisearchjson prepare()");
parent::prepare($args); parent::prepare($args);
$this->query = $this->trimmed('q'); $this->query = $this->trimmed('q');

View File

@ -29,6 +29,7 @@
* @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 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */
@ -99,19 +100,27 @@ class ApiStatusesDestroyAction extends ApiAuthAction
parent::handle($args); parent::handle($args);
if (!in_array($this->format, array('xml', 'json'))) { if (!in_array($this->format, array('xml', 'json'))) {
$this->clientError(_('API method not found.'), $code = 404); $this->clientError(
_('API method not found.'),
404
);
return; return;
} }
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) { if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
$this->clientError(_('This method requires a POST or DELETE.'), $this->clientError(
400, $this->format); _('This method requires a POST or DELETE.'),
400,
$this->format
);
return; return;
} }
if (empty($this->notice)) { if (empty($this->notice)) {
$this->clientError(_('No status found with that ID.'), $this->clientError(
404, $this->format); _('No status found with that ID.'),
404, $this->format
);
return; return;
} }
@ -122,8 +131,11 @@ class ApiStatusesDestroyAction extends ApiAuthAction
$this->notice->delete(); $this->notice->delete();
$this->showNotice(); $this->showNotice();
} else { } else {
$this->clientError(_('You may not delete another user\'s status.'), $this->clientError(
403, $this->format); _('You may not delete another user\'s status.'),
403,
$this->format
);
} }
} }

View File

@ -29,6 +29,7 @@
* @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 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -29,10 +29,102 @@
* @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-2010 StatusNet, Inc. * @copyright 2009-2010 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */
/* External API usage documentation. Please update when you change how this method works. */
/*! @page statusesupdate statuses/update
@section Description
Updates the authenticating user's status. Requires the status parameter specified below.
Request must be a POST.
@par URL pattern
/api/statuses/update.:format
@par Formats (:format)
xml, json
@par HTTP Method(s)
POST
@par Requires Authentication
Yes
@param status (Required) The URL-encoded text of the status update.
@param source (Optional) The source of the status.
@param in_reply_to_status_id (Optional) The ID of an existing status that the update is in reply to.
@param lat (Optional) The latitude the status refers to.
@param long (Optional) The longitude the status refers to.
@param media (Optional) a media upload, such as an image or movie file.
@sa @ref authentication
@sa @ref apiroot
@subsection usagenotes Usage notes
@li The URL pattern is relative to the @ref apiroot.
@li If the @e source parameter is not supplied the source of the status will default to 'api'.
@li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
to encode the latitude and longitude (see example response below <georss:point>).
@li Data uploaded via the @e media parameter should be multipart/form-data encoded.
@subsection exampleusage Example usage
@verbatim
curl -u username:password http://example.com/api/statuses/update.xml -d status='Howdy!' -d lat='30.468' -d long='-94.743'
@endverbatim
@subsection exampleresponse Example response
@verbatim
<?xml version="1.0" encoding="UTF-8"?>
<status>
<text>Howdy!</text>
<truncated>false</truncated>
<created_at>Tue Mar 30 23:28:05 +0000 2010</created_at>
<in_reply_to_status_id/>
<source>api</source>
<id>26668724</id>
<in_reply_to_user_id/>
<in_reply_to_screen_name/>
<geo xmlns:georss="http://www.georss.org/georss">
<georss:point>30.468 -94.743</georss:point>
</geo>
<favorited>false</favorited>
<user>
<id>25803</id>
<name>Jed Sanders</name>
<screen_name>jedsanders</screen_name>
<location>Hoop and Holler, Texas</location>
<description>I like to think of myself as America's Favorite.</description>
<profile_image_url>http://avatar.example.com/25803-48-20080924200604.png</profile_image_url>
<url>http://jedsanders.net</url>
<protected>false</protected>
<followers_count>5</followers_count>
<profile_background_color/>
<profile_text_color/>
<profile_link_color/>
<profile_sidebar_fill_color/>
<profile_sidebar_border_color/>
<friends_count>2</friends_count>
<created_at>Wed Sep 24 20:04:00 +0000 2008</created_at>
<favourites_count>0</favourites_count>
<utc_offset>0</utc_offset>
<time_zone>UTC</time_zone>
<profile_background_image_url/>
<profile_background_tile>false</profile_background_tile>
<statuses_count>70</statuses_count>
<following>true</following>
<notifications>true</notifications>
</user>
</status>
@endverbatim
*/
if (!defined('STATUSNET')) { if (!defined('STATUSNET')) {
exit(1); exit(1);
} }
@ -104,7 +196,8 @@ class ApiStatusesUpdateAction extends ApiAuthAction
if ($_SERVER['REQUEST_METHOD'] != 'POST') { if ($_SERVER['REQUEST_METHOD'] != 'POST') {
$this->clientError( $this->clientError(
_('This method requires a POST.'), _('This method requires a POST.'),
400, $this->format 400,
$this->format
); );
return; return;
} }
@ -125,7 +218,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
if (empty($this->status)) { if (empty($this->status)) {
$this->clientError( $this->clientError(
'Client must provide a \'status\' parameter with a value.', _('Client must provide a \'status\' parameter with a value.'),
400, 400,
$this->format $this->format
); );
@ -199,8 +292,8 @@ class ApiStatusesUpdateAction extends ApiAuthAction
try { try {
$upload = MediaFile::fromUpload('media', $this->auth_user); $upload = MediaFile::fromUpload('media', $this->auth_user);
} catch (ClientException $ce) { } catch (Exception $e) {
$this->clientError($ce->getMessage()); $this->clientError($e->getMessage(), $e->getCode(), $this->format);
return; return;
} }
@ -213,7 +306,11 @@ class ApiStatusesUpdateAction extends ApiAuthAction
'Max notice size is %d chars, ' . 'Max notice size is %d chars, ' .
'including attachment URL.' 'including attachment URL.'
); );
$this->clientError(sprintf($msg, Notice::maxContent())); $this->clientError(
sprintf($msg, Notice::maxContent()),
400,
$this->format
);
} }
} }
@ -240,7 +337,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
$options $options
); );
} catch (Exception $e) { } catch (Exception $e) {
$this->clientError($e->getMessage()); $this->clientError($e->getMessage(), $e->getCode(), $this->format);
return; return;
} }

View File

@ -206,7 +206,8 @@ class ApiSubscriptionsAction extends ApiBareAuthAction
{ {
switch ($this->format) { switch ($this->format) {
case 'xml': case 'xml':
$this->elementStart('users', array('type' => 'array')); $this->elementStart('users', array('type' => 'array',
'xmlns:statusnet' => 'http://status.net/schema/api/1/'));
foreach ($this->profiles as $profile) { foreach ($this->profiles as $profile) {
$this->showProfile( $this->showProfile(
$profile, $profile,

View File

@ -25,6 +25,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>
* @copyright 2009-2010 StatusNet, Inc. * @copyright 2009-2010 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -28,11 +28,107 @@
* @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.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */
/* External API usage documentation. Please update when you change how this method works. */
/*! @page friendstimeline statuses/friends_timeline
@section Description
Returns the 20 most recent statuses posted by the authenticating
user and that user's friends. This is the equivalent of "You and
friends" page in the web interface.
@par URL patterns
@li /api/statuses/friends_timeline.:format
@li /api/statuses/friends_timeline/:id.:format
@par Formats (:format)
xml, json, rss, atom
@par ID (:id)
username, user id
@par HTTP Method(s)
GET
@par Requires Authentication
Sometimes (see: @ref authentication)
@param user_id (Optional) Specifies a user by ID
@param screen_name (Optional) Specifies a user by screename (nickname)
@param since_id (Optional) Returns only statuses with an ID greater
than (that is, more recent than) the specified ID.
@param max_id (Optional) Returns only statuses with an ID less than
(that is, older than) or equal to the specified ID.
@param count (Optional) Specifies the number of statuses to retrieve.
@param page (Optional) Specifies the page of results to retrieve.
@sa @ref authentication
@sa @ref apiroot
@subsection usagenotes Usage notes
@li The URL pattern is relative to the @ref apiroot.
@li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
to encode the latitude and longitude (see example response below <georss:point>).
@subsection exampleusage Example usage
@verbatim
curl http://identi.ca/api/statuses/friends_timeline/evan.xml?count=1&page=2
@endverbatim
@subsection exampleresponse Example response
@verbatim
<?xml version="1.0"?>
<statuses type="array">
<status>
<text>back from the !yul !drupal meet with Evolving Web folk, @anarcat, @webchick and others, and an interesting refresher on SQL indexing</text>
<truncated>false</truncated>
<created_at>Wed Mar 31 01:33:02 +0000 2010</created_at>
<in_reply_to_status_id/>
<source>&lt;a href="http://code.google.com/p/microblog-purple/"&gt;mbpidgin&lt;/a&gt;</source>
<id>26674201</id>
<in_reply_to_user_id/>
<in_reply_to_screen_name/>
<geo/>
<favorited>false</favorited>
<user>
<id>246</id>
<name>Mark</name>
<screen_name>lambic</screen_name>
<location>Montreal, Canada</location>
<description>Geek</description>
<profile_image_url>http://avatar.identi.ca/246-48-20080702141545.png</profile_image_url>
<url>http://lambic.co.uk</url>
<protected>false</protected>
<followers_count>73</followers_count>
<profile_background_color>#F0F2F5</profile_background_color>
<profile_text_color/>
<profile_link_color>#002E6E</profile_link_color>
<profile_sidebar_fill_color>#CEE1E9</profile_sidebar_fill_color>
<profile_sidebar_border_color/>
<friends_count>58</friends_count>
<created_at>Wed Jul 02 14:12:15 +0000 2008</created_at>
<favourites_count>2</favourites_count>
<utc_offset>-14400</utc_offset>
<time_zone>US/Eastern</time_zone>
<profile_background_image_url/>
<profile_background_tile>false</profile_background_tile>
<statuses_count>933</statuses_count>
<following>false</following>
<notifications>false</notifications>
</user>
</status>
</statuses>
@endverbatim
*/
if (!defined('STATUSNET')) { if (!defined('STATUSNET')) {
exit(1); exit(1);
} }
@ -116,6 +212,7 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction
$id = "tag:$taguribase:FriendsTimeline:" . $this->user->id; $id = "tag:$taguribase:FriendsTimeline:" . $this->user->id;
$subtitle = sprintf( $subtitle = sprintf(
// TRANS: Message is used as a subtitle. %1$s is a user nickname, %2$s is a site name.
_('Updates from %1$s and friends on %2$s!'), _('Updates from %1$s and friends on %2$s!'),
$this->user->nickname, $this->user->nickname,
$sitename $sitename

View File

@ -25,7 +25,8 @@
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@status.net>
* @author Jeffery To <jeffery.to@gmail.com> * @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2009 StatusNet, Inc. * @copyright 2009-2010 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */
@ -137,7 +138,9 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction
$this->raw($atom->getString()); $this->raw($atom->getString());
} catch (Atom10FeedException $e) { } catch (Atom10FeedException $e) {
$this->serverError( $this->serverError(
'Could not generate feed for group - ' . $e->getMessage() 'Could not generate feed for group - ' . $e->getMessage(),
400,
$this->format
); );
return; return;
} }

View File

@ -29,6 +29,7 @@
* @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 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */
@ -117,6 +118,7 @@ class ApiTimelineHomeAction extends ApiBareAuthAction
$id = "tag:$taguribase:HomeTimeline:" . $this->user->id; $id = "tag:$taguribase:HomeTimeline:" . $this->user->id;
$subtitle = sprintf( $subtitle = sprintf(
// TRANS: Message is used as a subtitle. %1$s is a user nickname, %2$s is a site name.
_('Updates from %1$s and friends on %2$s!'), _('Updates from %1$s and friends on %2$s!'),
$this->user->nickname, $sitename $this->user->nickname, $sitename
); );

View File

@ -29,6 +29,7 @@
* @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 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -29,6 +29,7 @@
* @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 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */
@ -55,6 +56,95 @@ require_once INSTALLDIR . '/lib/apiprivateauth.php';
* @link http://status.net/ * @link http://status.net/
*/ */
/* External API usage documentation. Please update when you change how this method works. */
/*! @page publictimeline statuses/public_timeline
@section Description
Returns the 20 most recent notices from users throughout the system who have
uploaded their own avatars. Depending on configuration, it may or may not
not include notices from automatic posting services.
@par URL patterns
@li /api/statuses/public_timeline.:format
@par Formats (:format)
xml, json, rss, atom
@par HTTP Method(s)
GET
@par Requires Authentication
No
@param since_id (Optional) Returns only statuses with an ID greater
than (that is, more recent than) the specified ID.
@param max_id (Optional) Returns only statuses with an ID less than
(that is, older than) or equal to the specified ID.
@param count (Optional) Specifies the number of statuses to retrieve.
@param page (Optional) Specifies the page of results to retrieve.
@sa @ref apiroot
@subsection usagenotes Usage notes
@li The URL pattern is relative to the @ref apiroot.
@li The XML response uses <a href="http://georss.org/Main_Page">GeoRSS</a>
to encode the latitude and longitude (see example response below <georss:point>).
@subsection exampleusage Example usage
@verbatim
curl http://identi.ca/api/statuses/friends_timeline/evan.xml?count=1&page=2
@endverbatim
@subsection exampleresponse Example response
@verbatim
<?xml version="1.0" encoding="UTF-8"?>
<statuses type="array">
<status>
<text>@skwashd oh, commbank reenabled me super quick both times. but disconcerting when you don't expect it though</text>
<truncated>false</truncated>
<created_at>Sat Apr 17 00:49:12 +0000 2010</created_at>
<in_reply_to_status_id>28838393</in_reply_to_status_id>
<source>xmpp</source>
<id>28838456</id>
<in_reply_to_user_id>39303</in_reply_to_user_id>
<in_reply_to_screen_name>skwashd</in_reply_to_screen_name>
<geo></geo>
<favorited>false</favorited>
<user>
<id>44517</id>
<name>joshua may</name>
<screen_name>notjosh</screen_name>
<location></location>
<description></description>
<profile_image_url>http://avatar.identi.ca/44517-48-20090321004106.jpeg</profile_image_url>
<url></url>
<protected>false</protected>
<followers_count>17</followers_count>
<profile_background_color></profile_background_color>
<profile_text_color></profile_text_color>
<profile_link_color></profile_link_color>
<profile_sidebar_fill_color></profile_sidebar_fill_color>
<profile_sidebar_border_color></profile_sidebar_border_color>
<friends_count>20</friends_count>
<created_at>Sat Mar 21 00:40:25 +0000 2009</created_at>
<favourites_count>0</favourites_count>
<utc_offset>0</utc_offset>
<time_zone>UTC</time_zone>
<profile_background_image_url></profile_background_image_url>
<profile_background_tile>false</profile_background_tile>
<statuses_count>100</statuses_count>
<following>false</following>
<notifications>false</notifications>
</user>
</status>
[....]
</statuses>
@endverbatim
*/
class ApiTimelinePublicAction extends ApiPrivateAuthAction class ApiTimelinePublicAction extends ApiPrivateAuthAction
{ {

View File

@ -26,6 +26,7 @@
* @author Jeffery To <jeffery.to@gmail.com> * @author Jeffery To <jeffery.to@gmail.com>
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@status.net>
* @copyright 2009-2010 StatusNet, Inc. * @copyright 2009-2010 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -29,6 +29,7 @@
* @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 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -22,7 +22,7 @@
* @category Search * @category Search
* @package StatusNet * @package StatusNet
* @author Zach Copley <zach@status.net> * @author Zach Copley <zach@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/
*/ */
@ -31,6 +31,8 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1); exit(1);
} }
require_once INSTALLDIR.'/lib/apiprivateauth.php';
/** /**
* Returns the top ten queries that are currently trending * Returns the top ten queries that are currently trending
* *
@ -43,7 +45,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @see ApiAction * @see ApiAction
*/ */
class TwitapitrendsAction extends ApiAction class ApiTrendsAction extends ApiPrivateAuthAction
{ {
var $callback; var $callback;
@ -82,7 +84,7 @@ class TwitapitrendsAction extends ApiAction
*/ */
function showTrends() function showTrends()
{ {
$this->serverError(_('API method under construction.'), $code = 501); $this->serverError(_('API method under construction.'), 501);
} }
} }

View File

@ -113,7 +113,7 @@ class ApiUserShowAction extends ApiPrivateAuthAction
if ($this->format == 'xml') { if ($this->format == 'xml') {
$this->initDocument('xml'); $this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user); $this->showTwitterXmlUser($twitter_user, 'user', true);
$this->endDocument('xml'); $this->endDocument('xml');
} elseif ($this->format == 'json') { } elseif ($this->format == 'json') {
$this->initDocument('json'); $this->initDocument('json');

View File

@ -148,8 +148,20 @@ class BlockAction extends ProfileFormAction
$this->hidden($k, $v); $this->hidden($k, $v);
} }
} }
$this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not block this user")); $this->submit('form_action-no',
$this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Block this user')); // TRANS: Button label on the user block form.
_m('BUTTON','No'),
'submit form_action-primary',
'no',
// TRANS: Submit button title for 'No' when blocking a user.
_('Do not block this user'));
$this->submit('form_action-yes',
// TRANS: Button label on the user block form.
_m('BUTTON','Yes'),
'submit form_action-secondary',
'yes',
// TRANS: Submit button title for 'Yes' when blocking a user.
_('Block this user'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }

View File

@ -87,10 +87,12 @@ class ConfirmaddressAction extends Action
} }
$type = $confirm->address_type; $type = $confirm->address_type;
if (!in_array($type, array('email', 'jabber', 'sms'))) { if (!in_array($type, array('email', 'jabber', 'sms'))) {
// TRANS: Server error for an unknow address type, which can be 'email', 'jabber', or 'sms'.
$this->serverError(sprintf(_('Unrecognized address type %s.'), $type)); $this->serverError(sprintf(_('Unrecognized address type %s.'), $type));
return; return;
} }
if ($cur->$type == $confirm->address) { if ($cur->$type == $confirm->address) {
// TRANS: Client error for an already confirmed email/jabbel/sms address.
$this->clientError(_('That address has already been confirmed.')); $this->clientError(_('That address has already been confirmed.'));
return; return;
} }

View File

@ -150,13 +150,17 @@ class DeleteapplicationAction extends Action
'This will clear all data about the application from the '. 'This will clear all data about the application from the '.
'database, including all existing user connections.')); 'database, including all existing user connections.'));
$this->submit('form_action-no', $this->submit('form_action-no',
_('No'), // TRANS: Button label on the delete application form.
_m('BUTTON','No'),
'submit form_action-primary', 'submit form_action-primary',
'no', 'no',
_("Do not delete this application")); // TRANS: Submit button title for 'No' when deleting an application.
_('Do not delete this application'));
$this->submit('form_action-yes', $this->submit('form_action-yes',
_('Yes'), // TRANS: Button label on the delete application form.
_m('BUTTON','Yes'),
'submit form_action-secondary', 'submit form_action-secondary',
// TRANS: Submit button title for 'Yes' when deleting an application.
'yes', _('Delete this application')); 'yes', _('Delete this application'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');

View File

@ -142,8 +142,20 @@ class DeletenoticeAction extends Action
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
$this->hidden('notice', $this->trimmed('notice')); $this->hidden('notice', $this->trimmed('notice'));
$this->element('p', null, _('Are you sure you want to delete this notice?')); $this->element('p', null, _('Are you sure you want to delete this notice?'));
$this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not delete this notice")); $this->submit('form_action-no',
$this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Delete this notice')); // TRANS: Button label on the delete notice form.
_m('BUTTON','No'),
'submit form_action-primary',
'no',
// TRANS: Submit button title for 'No' when deleting a notice.
_("Do not delete this notice"));
$this->submit('form_action-yes',
// TRANS: Button label on the delete notice form.
_m('BUTTON','Yes'),
'submit form_action-secondary',
'yes',
// TRANS: Submit button title for 'Yes' when deleting a notice.
_('Delete this notice'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }

View File

@ -147,8 +147,20 @@ class DeleteuserAction extends ProfileFormAction
} }
Event::handle('EndDeleteUserForm', array($this, $this->user)); Event::handle('EndDeleteUserForm', array($this, $this->user));
} }
$this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not block this user")); $this->submit('form_action-no',
$this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Delete this user')); // TRANS: Button label on the delete user form.
_m('BUTTON','No'),
'submit form_action-primary',
'no',
// TRANS: Submit button title for 'No' when deleting a user.
_('Do not block this user'));
$this->submit('form_action-yes',
// TRANS: Button label on the delete user form.
_m('BUTTON','Yes'),
'submit form_action-secondary',
'yes',
// TRANS: Submit button title for 'Yes' when deleting a user.
_('Delete this user'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }

View File

@ -59,6 +59,7 @@ class DesignadminpanelAction extends AdminPanelAction
function title() function title()
{ {
// TRANS: Message used as title for design settings for the site.
return _('Design'); return _('Design');
} }
@ -125,9 +126,19 @@ class DesignadminpanelAction extends AdminPanelAction
return; return;
} }
// check for an image upload // check for file uploads
$bgimage = $this->saveBackgroundImage(); $bgimage = $this->saveBackgroundImage();
$customTheme = $this->saveCustomTheme();
$oldtheme = common_config('site', 'theme');
if ($customTheme) {
// This feels pretty hacky :D
$this->args['theme'] = $customTheme;
$themeChanged = true;
} else {
$themeChanged = ($this->trimmed('theme') != $oldtheme);
}
static $settings = array('theme', 'logo'); static $settings = array('theme', 'logo');
@ -139,15 +150,13 @@ class DesignadminpanelAction extends AdminPanelAction
$this->validate($values); $this->validate($values);
$oldtheme = common_config('site', 'theme');
$config = new Config(); $config = new Config();
$config->query('BEGIN'); $config->query('BEGIN');
// Only update colors if the theme has not changed. // Only update colors if the theme has not changed.
if ($oldtheme == $values['theme']) { if (!$themeChanged) {
$bgcolor = new WebColor($this->trimmed('design_background')); $bgcolor = new WebColor($this->trimmed('design_background'));
$ccolor = new WebColor($this->trimmed('design_content')); $ccolor = new WebColor($this->trimmed('design_content'));
@ -189,6 +198,13 @@ class DesignadminpanelAction extends AdminPanelAction
Config::save('design', 'backgroundimage', $bgimage); Config::save('design', 'backgroundimage', $bgimage);
} }
if (common_config('custom_css', 'enabled')) {
$css = $this->arg('css');
if ($css != common_config('custom_css', 'css')) {
Config::save('custom_css', 'css', $css);
}
}
$config->query('COMMIT'); $config->query('COMMIT');
} }
@ -262,6 +278,33 @@ class DesignadminpanelAction extends AdminPanelAction
} }
} }
/**
* Save the custom theme if the user uploaded one.
*
* @return mixed custom theme name, if succesful, or null if no theme upload.
* @throws ClientException for invalid theme archives
* @throws ServerException if trouble saving the theme files
*/
function saveCustomTheme()
{
if (common_config('theme_upload', 'enabled') &&
$_FILES['design_upload_theme']['error'] == UPLOAD_ERR_OK) {
$upload = ThemeUploader::fromUpload('design_upload_theme');
$basedir = common_config('local', 'dir');
if (empty($basedir)) {
$basedir = INSTALLDIR . '/local';
}
$name = 'custom'; // @todo allow multiples, custom naming?
$outdir = $basedir . '/theme/' . $name;
$upload->extract($outdir);
return $name;
} else {
return null;
}
}
/** /**
* Attempt to validate setting values * Attempt to validate setting values
* *
@ -370,7 +413,15 @@ class DesignAdminPanelForm extends AdminForm
function formData() function formData()
{ {
$this->showLogo();
$this->showTheme();
$this->showBackground();
$this->showColors();
$this->showAdvanced();
}
function showLogo()
{
$this->out->elementStart('fieldset', array('id' => 'settings_design_logo')); $this->out->elementStart('fieldset', array('id' => 'settings_design_logo'));
$this->out->element('legend', null, _('Change logo')); $this->out->element('legend', null, _('Change logo'));
@ -383,6 +434,11 @@ class DesignAdminPanelForm extends AdminForm
$this->out->elementEnd('ul'); $this->out->elementEnd('ul');
$this->out->elementEnd('fieldset'); $this->out->elementEnd('fieldset');
}
function showTheme()
{
$this->out->elementStart('fieldset', array('id' => 'settings_design_theme')); $this->out->elementStart('fieldset', array('id' => 'settings_design_theme'));
$this->out->element('legend', null, _('Change theme')); $this->out->element('legend', null, _('Change theme'));
@ -406,10 +462,23 @@ class DesignAdminPanelForm extends AdminForm
false, $this->value('theme')); false, $this->value('theme'));
$this->unli(); $this->unli();
if (common_config('theme_upload', 'enabled')) {
$this->li();
$this->out->element('label', array('for' => 'design_upload_theme'), _('Custom theme'));
$this->out->element('input', array('id' => 'design_upload_theme',
'name' => 'design_upload_theme',
'type' => 'file'));
$this->out->element('p', 'form_guide', _('You can upload a custom StatusNet theme as a .ZIP archive.'));
$this->unli();
}
$this->out->elementEnd('ul'); $this->out->elementEnd('ul');
$this->out->elementEnd('fieldset'); $this->out->elementEnd('fieldset');
}
function showBackground()
{
$design = $this->out->design; $design = $this->out->design;
$this->out->elementStart('fieldset', array('id' => $this->out->elementStart('fieldset', array('id' =>
@ -454,6 +523,7 @@ class DesignAdminPanelForm extends AdminForm
$this->out->element('label', array('for' => 'design_background-image_on', $this->out->element('label', array('for' => 'design_background-image_on',
'class' => 'radio'), 'class' => 'radio'),
// TRANS: Used as radio button label to add a background image.
_('On')); _('On'));
$attrs = array('name' => 'design_background-image_onoff', $attrs = array('name' => 'design_background-image_onoff',
@ -470,6 +540,7 @@ class DesignAdminPanelForm extends AdminForm
$this->out->element('label', array('for' => 'design_background-image_off', $this->out->element('label', array('for' => 'design_background-image_off',
'class' => 'radio'), 'class' => 'radio'),
// TRANS: Used as radio button label to not add a background image.
_('Off')); _('Off'));
$this->out->element('p', 'form_guide', _('Turn background image on or off.')); $this->out->element('p', 'form_guide', _('Turn background image on or off.'));
$this->unli(); $this->unli();
@ -483,6 +554,11 @@ class DesignAdminPanelForm extends AdminForm
$this->out->elementEnd('ul'); $this->out->elementEnd('ul');
$this->out->elementEnd('fieldset'); $this->out->elementEnd('fieldset');
}
function showColors()
{
$design = $this->out->design;
$this->out->elementStart('fieldset', array('id' => 'settings_design_color')); $this->out->elementStart('fieldset', array('id' => 'settings_design_color'));
$this->out->element('legend', null, _('Change colours')); $this->out->element('legend', null, _('Change colours'));
@ -490,6 +566,7 @@ class DesignAdminPanelForm extends AdminForm
$this->out->elementStart('ul', 'form_data'); $this->out->elementStart('ul', 'form_data');
try { try {
// @fixme avoid loop unrolling in non-performance-critical contexts like this
$bgcolor = new WebColor($design->backgroundcolor); $bgcolor = new WebColor($design->backgroundcolor);
@ -557,6 +634,7 @@ class DesignAdminPanelForm extends AdminForm
$this->unli(); $this->unli();
} catch (WebColorException $e) { } catch (WebColorException $e) {
// @fixme normalize them individually!
common_log(LOG_ERR, 'Bad color values in site design: ' . common_log(LOG_ERR, 'Bad color values in site design: ' .
$e->getMessage()); $e->getMessage());
} }
@ -566,6 +644,27 @@ class DesignAdminPanelForm extends AdminForm
$this->out->elementEnd('ul'); $this->out->elementEnd('ul');
} }
function showAdvanced()
{
if (common_config('custom_css', 'enabled')) {
$this->out->elementStart('fieldset', array('id' => 'settings_design_advanced'));
$this->out->element('legend', null, _('Advanced'));
$this->out->elementStart('ul', 'form_data');
$this->li();
$this->out->element('label', array('for' => 'css'), _('Custom CSS'));
$this->out->element('textarea', array('name' => 'css',
'id' => 'css',
'cols' => '50',
'rows' => '10'),
strval(common_config('custom_css', 'css')));
$this->unli();
$this->out->elementEnd('fieldset');
$this->out->elementEnd('ul');
}
}
/** /**
* Action elements * Action elements
* *

View File

@ -57,6 +57,7 @@ class EmailsettingsAction extends AccountSettingsAction
function title() function title()
{ {
// TRANS: Title for e-mail settings.
return _('Email settings'); return _('Email settings');
} }
@ -68,6 +69,10 @@ class EmailsettingsAction extends AccountSettingsAction
function getInstructions() function getInstructions()
{ {
// XXX: For consistency of parameters in messages, this should be a
// regular parameters, replaced with sprintf().
// TRANS: E-mail settings page instructions.
// TRANS: %%site.name%% is the name of the site.
return _('Manage how you get email from %%site.name%%.'); return _('Manage how you get email from %%site.name%%.');
} }
@ -97,102 +102,126 @@ class EmailsettingsAction extends AccountSettingsAction
common_local_url('emailsettings'))); common_local_url('emailsettings')));
$this->elementStart('fieldset'); $this->elementStart('fieldset');
$this->elementStart('fieldset', array('id' => 'settings_email_address')); $this->elementStart('fieldset', array('id' => 'settings_email_address'));
$this->element('legend', null, _('Address')); // TRANS: Form legend for e-mail settings form.
$this->element('legend', null, _('Email address'));
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
if ($user->email) { if ($user->email) {
$this->element('p', array('id' => 'form_confirmed'), $user->email); $this->element('p', array('id' => 'form_confirmed'), $user->email);
// TRANS: Form note in e-mail settings form.
$this->element('p', array('class' => 'form_note'), _('Current confirmed email address.')); $this->element('p', array('class' => 'form_note'), _('Current confirmed email address.'));
$this->hidden('email', $user->email); $this->hidden('email', $user->email);
$this->submit('remove', _('Remove')); // TRANS: Button label to remove a confirmed e-mail address.
$this->submit('remove', _m('BUTTON','Remove'));
} else { } else {
$confirm = $this->getConfirmation(); $confirm = $this->getConfirmation();
if ($confirm) { if ($confirm) {
$this->element('p', array('id' => 'form_unconfirmed'), $confirm->address); $this->element('p', array('id' => 'form_unconfirmed'), $confirm->address);
// TRANS: Form note in e-mail settings form.
$this->element('p', array('class' => 'form_note'), $this->element('p', array('class' => 'form_note'),
_('Awaiting confirmation on this address. '. _('Awaiting confirmation on this address. '.
'Check your inbox (and spam box!) for a message '. 'Check your inbox (and spam box!) for a message '.
'with further instructions.')); 'with further instructions.'));
$this->hidden('email', $confirm->address); $this->hidden('email', $confirm->address);
$this->submit('cancel', _('Cancel')); // TRANS: Button label to cancel an e-mail address confirmation procedure.
$this->submit('cancel', _m('BUTTON','Cancel'));
} else { } else {
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Field label for e-mail address input in e-mail settings form.
$this->input('email', _('Email address'), $this->input('email', _('Email address'),
($this->arg('email')) ? $this->arg('email') : null, ($this->arg('email')) ? $this->arg('email') : null,
// TRANS: Instructions for e-mail address input form.
_('Email address, like "UserName@example.org"')); _('Email address, like "UserName@example.org"'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->submit('add', _('Add')); // TRANS: Button label for adding an e-mail address in e-mail settings form.
$this->submit('add', _m('BUTTON','Add'));
} }
} }
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
if (common_config('emailpost', 'enabled') && $user->email) { if (common_config('emailpost', 'enabled') && $user->email) {
$this->elementStart('fieldset', array('id' => 'settings_email_incoming')); $this->elementStart('fieldset', array('id' => 'settings_email_incoming'));
// TRANS: Form legend for incoming e-mail settings form.
$this->element('legend', null, _('Incoming email')); $this->element('legend', null, _('Incoming email'));
if ($user->incomingemail) { if ($user->incomingemail) {
$this->elementStart('p'); $this->elementStart('p');
$this->element('span', 'address', $user->incomingemail); $this->element('span', 'address', $user->incomingemail);
// XXX: Looks a little awkward in the UI.
// Something like "xxxx@identi.ca Send email ..". Needs improvement.
$this->element('span', 'input_instructions', $this->element('span', 'input_instructions',
// TRANS: Form instructions for incoming e-mail form in e-mail settings.
_('Send email to this address to post new notices.')); _('Send email to this address to post new notices.'));
$this->elementEnd('p'); $this->elementEnd('p');
$this->submit('removeincoming', _('Remove')); // TRANS: Button label for removing a set sender e-mail address to post notices from.
$this->submit('removeincoming', _m('BUTTON','Remove'));
} }
$this->elementStart('p'); $this->elementStart('p');
$this->element('span', 'input_instructions', $this->element('span', 'input_instructions',
// TRANS: Instructions for incoming e-mail address input form.
_('Make a new email address for posting to; '. _('Make a new email address for posting to; '.
'cancels the old one.')); 'cancels the old one.'));
$this->elementEnd('p'); $this->elementEnd('p');
$this->submit('newincoming', _('New')); // TRANS: Button label for adding an e-mail address to send notices from.
$this->submit('newincoming', _m('BUTTON','New'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
} }
$this->elementStart('fieldset', array('id' => 'settings_email_preferences')); $this->elementStart('fieldset', array('id' => 'settings_email_preferences'));
$this->element('legend', null, _('Preferences')); // TRANS: Form legend for e-mail preferences form.
$this->element('legend', null, _('Email preferences'));
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('emailnotifysub', $this->checkbox('emailnotifysub',
// TRANS: Checkbox label in e-mail preferences form.
_('Send me notices of new subscriptions through email.'), _('Send me notices of new subscriptions through email.'),
$user->emailnotifysub); $user->emailnotifysub);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('emailnotifyfav', $this->checkbox('emailnotifyfav',
// TRANS: Checkbox label in e-mail preferences form.
_('Send me email when someone '. _('Send me email when someone '.
'adds my notice as a favorite.'), 'adds my notice as a favorite.'),
$user->emailnotifyfav); $user->emailnotifyfav);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('emailnotifymsg', $this->checkbox('emailnotifymsg',
// TRANS: Checkbox label in e-mail preferences form.
_('Send me email when someone sends me a private message.'), _('Send me email when someone sends me a private message.'),
$user->emailnotifymsg); $user->emailnotifymsg);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('emailnotifyattn', $this->checkbox('emailnotifyattn',
// TRANS: Checkbox label in e-mail preferences form.
_('Send me email when someone sends me an "@-reply".'), _('Send me email when someone sends me an "@-reply".'),
$user->emailnotifyattn); $user->emailnotifyattn);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('emailnotifynudge', $this->checkbox('emailnotifynudge',
// TRANS: Checkbox label in e-mail preferences form.
_('Allow friends to nudge me and send me an email.'), _('Allow friends to nudge me and send me an email.'),
$user->emailnotifynudge); $user->emailnotifynudge);
$this->elementEnd('li'); $this->elementEnd('li');
if (common_config('emailpost', 'enabled')) { if (common_config('emailpost', 'enabled')) {
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('emailpost', $this->checkbox('emailpost',
// TRANS: Checkbox label in e-mail preferences form.
_('I want to post notices by email.'), _('I want to post notices by email.'),
$user->emailpost); $user->emailpost);
$this->elementEnd('li'); $this->elementEnd('li');
} }
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('emailmicroid', $this->checkbox('emailmicroid',
// TRANS: Checkbox label in e-mail preferences form.
_('Publish a MicroID for my email address.'), _('Publish a MicroID for my email address.'),
$user->emailmicroid); $user->emailmicroid);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->submit('save', _('Save')); // TRANS: Button label to save e-mail preferences.
$this->submit('save', _m('BUTTON','Save'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
@ -253,6 +282,7 @@ class EmailsettingsAction extends AccountSettingsAction
} else if ($this->arg('newincoming')) { } else if ($this->arg('newincoming')) {
$this->newIncoming(); $this->newIncoming();
} else { } else {
// TRANS: Message given submitting a form with an unknown action in e-mail settings.
$this->showForm(_('Unexpected form submission.')); $this->showForm(_('Unexpected form submission.'));
} }
} }
@ -293,13 +323,15 @@ class EmailsettingsAction extends AccountSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error updating e-mail preferences.
$this->serverError(_('Couldn\'t update user.')); $this->serverError(_('Couldn\'t update user.'));
return; return;
} }
$user->query('COMMIT'); $user->query('COMMIT');
$this->showForm(_('Preferences saved.'), true); // TRANS: Confirmation message for successful e-mail preferences save.
$this->showForm(_('Email preferences saved.'), true);
} }
/** /**
@ -317,6 +349,7 @@ class EmailsettingsAction extends AccountSettingsAction
// Some validation // Some validation
if (!$email) { if (!$email) {
// TRANS: Message given saving e-mail address without having provided one.
$this->showForm(_('No email address.')); $this->showForm(_('No email address.'));
return; return;
} }
@ -324,16 +357,20 @@ class EmailsettingsAction extends AccountSettingsAction
$email = common_canonical_email($email); $email = common_canonical_email($email);
if (!$email) { if (!$email) {
// TRANS: Message given saving e-mail address that cannot be normalised.
$this->showForm(_('Cannot normalize that email address')); $this->showForm(_('Cannot normalize that email address'));
return; return;
} }
if (!Validate::email($email, common_config('email', 'check_domain'))) { if (!Validate::email($email, common_config('email', 'check_domain'))) {
// TRANS: Message given saving e-mail address that not valid.
$this->showForm(_('Not a valid email address.')); $this->showForm(_('Not a valid email address.'));
return; return;
} else if ($user->email == $email) { } else if ($user->email == $email) {
// TRANS: Message given saving e-mail address that is already set.
$this->showForm(_('That is already your email address.')); $this->showForm(_('That is already your email address.'));
return; return;
} else if ($this->emailExists($email)) { } else if ($this->emailExists($email)) {
// TRANS: Message given saving e-mail address that is already set for another user.
$this->showForm(_('That email address already belongs '. $this->showForm(_('That email address already belongs '.
'to another user.')); 'to another user.'));
return; return;
@ -350,12 +387,14 @@ class EmailsettingsAction extends AccountSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($confirm, 'INSERT', __FILE__); common_log_db_error($confirm, 'INSERT', __FILE__);
// TRANS: Server error thrown on database error adding e-mail confirmation code.
$this->serverError(_('Couldn\'t insert confirmation code.')); $this->serverError(_('Couldn\'t insert confirmation code.'));
return; return;
} }
mail_confirm_address($user, $confirm->code, $user->nickname, $email); mail_confirm_address($user, $confirm->code, $user->nickname, $email);
// TRANS: Message given saving valid e-mail address that is to be confirmed.
$msg = _('A confirmation code was sent to the email address you added. '. $msg = _('A confirmation code was sent to the email address you added. '.
'Check your inbox (and spam box!) for the code and instructions '. 'Check your inbox (and spam box!) for the code and instructions '.
'on how to use it.'); 'on how to use it.');
@ -376,11 +415,13 @@ class EmailsettingsAction extends AccountSettingsAction
$confirm = $this->getConfirmation(); $confirm = $this->getConfirmation();
if (!$confirm) { if (!$confirm) {
// TRANS: Message given canceling e-mail address confirmation that is not pending.
$this->showForm(_('No pending confirmation to cancel.')); $this->showForm(_('No pending confirmation to cancel.'));
return; return;
} }
if ($confirm->address != $email) { if ($confirm->address != $email) {
$this->showForm(_('That is the wrong IM address.')); // TRANS: Message given canceling e-mail address confirmation for the wrong e-mail address.
$this->showForm(_('That is the wrong email address.'));
return; return;
} }
@ -388,11 +429,13 @@ class EmailsettingsAction extends AccountSettingsAction
if (!$result) { if (!$result) {
common_log_db_error($confirm, 'DELETE', __FILE__); common_log_db_error($confirm, 'DELETE', __FILE__);
// TRANS: Server error thrown on database error canceling e-mail address confirmation.
$this->serverError(_('Couldn\'t delete email confirmation.')); $this->serverError(_('Couldn\'t delete email confirmation.'));
return; return;
} }
$this->showForm(_('Confirmation cancelled.'), true); // TRANS: Message given after successfully canceling e-mail address confirmation.
$this->showForm(_('Email confirmation cancelled.'), true);
} }
/** /**
@ -410,6 +453,8 @@ class EmailsettingsAction extends AccountSettingsAction
// Maybe an old tab open...? // Maybe an old tab open...?
if ($user->email != $email) { if ($user->email != $email) {
// TRANS: Message given trying to remove an e-mail address that is not
// TRANS: registered for the active user.
$this->showForm(_('That is not your email address.')); $this->showForm(_('That is not your email address.'));
return; return;
} }
@ -424,12 +469,14 @@ class EmailsettingsAction extends AccountSettingsAction
if (!$result) { if (!$result) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error removing a registered e-mail address.
$this->serverError(_('Couldn\'t update user.')); $this->serverError(_('Couldn\'t update user.'));
return; return;
} }
$user->query('COMMIT'); $user->query('COMMIT');
$this->showForm(_('The address was removed.'), true); // TRANS: Message given after successfully removing a registered e-mail address.
$this->showForm(_('The email address was removed.'), true);
} }
/** /**
@ -453,9 +500,11 @@ class EmailsettingsAction extends AccountSettingsAction
if (!$user->updateKeys($orig)) { if (!$user->updateKeys($orig)) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error removing incoming e-mail address.
$this->serverError(_("Couldn't update user record.")); $this->serverError(_("Couldn't update user record."));
} }
// TRANS: Message given after successfully removing an incoming e-mail address.
$this->showForm(_('Incoming email address removed.'), true); $this->showForm(_('Incoming email address removed.'), true);
} }
@ -475,9 +524,11 @@ class EmailsettingsAction extends AccountSettingsAction
if (!$user->updateKeys($orig)) { if (!$user->updateKeys($orig)) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error adding incoming e-mail address.
$this->serverError(_("Couldn't update user record.")); $this->serverError(_("Couldn't update user record."));
} }
// TRANS: Message given after successfully adding an incoming e-mail address.
$this->showForm(_('New incoming email address added.'), true); $this->showForm(_('New incoming email address added.'), true);
} }

View File

@ -104,7 +104,7 @@ class FavorAction extends Action
} }
/** /**
* Notifies a user when his notice is favorited. * Notifies a user when their notice is favorited.
* *
* @param class $notice favorited notice * @param class $notice favorited notice
* @param class $user user declaring a favorite * @param class $user user declaring a favorite

View File

@ -37,7 +37,7 @@ require_once INSTALLDIR.'/lib/omb.php';
* Handler for remote subscription finish callback * Handler for remote subscription finish callback
* *
* When a remote user subscribes a local user, a redirect to this action is * When a remote user subscribes a local user, a redirect to this action is
* issued after the remote user authorized his service to subscribe. * issued after the remote user authorized their service to subscribe.
* *
* @category Action * @category Action
* @package Laconica * @package Laconica

View File

@ -95,7 +95,9 @@ class FoafAction extends Action
// Would be nice to tell if they were a Person or not (e.g. a #person usertag?) // Would be nice to tell if they were a Person or not (e.g. a #person usertag?)
$this->elementStart('Agent', array('rdf:about' => $this->elementStart('Agent', array('rdf:about' =>
$this->user->uri)); $this->user->uri));
if ($this->user->email) {
$this->element('mbox_sha1sum', null, sha1('mailto:' . $this->user->email)); $this->element('mbox_sha1sum', null, sha1('mailto:' . $this->user->email));
}
if ($this->profile->fullname) { if ($this->profile->fullname) {
$this->element('name', null, $this->profile->fullname); $this->element('name', null, $this->profile->fullname);
} }
@ -152,7 +154,9 @@ class FoafAction extends Action
} }
$person = $this->showMicrobloggingAccount($this->profile, $person = $this->showMicrobloggingAccount($this->profile,
common_root_url(), $this->user->uri, false); common_root_url(), $this->user->uri,
/*$fetchSubscriptions*/true,
/*$isSubscriber*/false);
// Get people who subscribe to user // Get people who subscribe to user
@ -207,7 +211,8 @@ class FoafAction extends Action
$this->showMicrobloggingAccount($profile, $this->showMicrobloggingAccount($profile,
($local == 'local') ? common_root_url() : null, ($local == 'local') ? common_root_url() : null,
$uri, $uri,
true); /*$fetchSubscriptions*/false,
/*$isSubscriber*/($type == LISTENER || $type == BOTH));
if ($foaf_url) { if ($foaf_url) {
$this->element('rdfs:seeAlso', array('rdf:resource' => $foaf_url)); $this->element('rdfs:seeAlso', array('rdf:resource' => $foaf_url));
} }
@ -232,7 +237,21 @@ class FoafAction extends Action
$this->elementEnd('PersonalProfileDocument'); $this->elementEnd('PersonalProfileDocument');
} }
function showMicrobloggingAccount($profile, $service=null, $useruri=null, $isSubscriber=false) /**
* Output FOAF <account> bit for the given profile.
*
* @param Profile $profile
* @param mixed $service Root URL of this StatusNet instance for a local
* user, otherwise null.
* @param mixed $useruri URI string for the referenced profile..
* @param boolean $fetchSubscriptions Should we load and list all their subscriptions?
* @param boolean $isSubscriber if not fetching subs, we can still mark the user as following the current page.
*
* @return array if $fetchSubscribers is set, return a list of info on those
* subscriptions.
*/
function showMicrobloggingAccount($profile, $service=null, $useruri=null, $fetchSubscriptions=false, $isSubscriber=false)
{ {
$attr = array(); $attr = array();
if ($useruri) { if ($useruri) {
@ -254,9 +273,7 @@ class FoafAction extends Action
$person = array(); $person = array();
if ($isSubscriber) { if ($fetchSubscriptions) {
$this->element('sioc:follows', array('rdf:resource'=>$this->user->uri . '#acct'));
} else {
// Get people user is subscribed to // Get people user is subscribed to
$sub = new Subscription(); $sub = new Subscription();
$sub->subscriber = $profile->id; $sub->subscriber = $profile->id;
@ -281,6 +298,9 @@ class FoafAction extends Action
} }
unset($sub); unset($sub);
} else if ($isSubscriber) {
// Just declare that they follow the user whose FOAF we're showing.
$this->element('sioc:follows', array('rdf:resource' => $this->user->uri . '#acct'));
} }
$this->elementEnd('OnlineAccount'); $this->elementEnd('OnlineAccount');

View File

@ -37,6 +37,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* @category Action * @category Action
* @package StatusNet * @package StatusNet
* @author Craig Andrews <candrews@integralblue.com> * @author Craig Andrews <candrews@integralblue.com>
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */

View File

@ -173,8 +173,20 @@ class GroupblockAction extends RedirectingAction
$this->hidden($k, $v); $this->hidden($k, $v);
} }
} }
$this->submit('form_action-no', _('No'), 'submit form_action-primary', 'no', _("Do not block this user from this group")); $this->submit('form_action-no',
$this->submit('form_action-yes', _('Yes'), 'submit form_action-secondary', 'yes', _('Block this user from this group')); // TRANS: Button label on the form to block a user from a group.
_m('BUTTON','No'),
'submit form_action-primary',
'no',
// TRANS: Submit button title for 'No' when blocking a user from a group.
_('Do not block this user from this group'));
$this->submit('form_action-yes',
// TRANS: Button label on the form to block a user from a group.
_m('BUTTON','Yes'),
'submit form_action-secondary',
'yes',
// TRANS: Submit button title for 'Yes' when blocking a user from a group.
_('Block this user from this group'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }

View File

@ -135,8 +135,10 @@ class groupRssAction extends Rss10Action
$c = array('url' => common_local_url('grouprss', $c = array('url' => common_local_url('grouprss',
array('nickname' => array('nickname' =>
$group->nickname)), $group->nickname)),
// TRANS: Message is used as link title. %s is a user nickname.
'title' => sprintf(_('%s timeline'), $group->nickname), 'title' => sprintf(_('%s timeline'), $group->nickname),
'link' => common_local_url('showgroup', array('nickname' => $group->nickname)), 'link' => common_local_url('showgroup', array('nickname' => $group->nickname)),
// TRANS: Message is used as link description. %1$s is a username, %2$s is a site name.
'description' => sprintf(_('Updates from members of %1$s on %2$s!'), 'description' => sprintf(_('Updates from members of %1$s on %2$s!'),
$group->nickname, common_config('site', 'name'))); $group->nickname, common_config('site', 'name')));
return $c; return $c;

View File

@ -56,6 +56,7 @@ class ImsettingsAction extends ConnectSettingsAction
function title() function title()
{ {
// TRANS: Title for instance messaging settings.
return _('IM settings'); return _('IM settings');
} }
@ -67,6 +68,9 @@ class ImsettingsAction extends ConnectSettingsAction
function getInstructions() function getInstructions()
{ {
// TRANS: Instant messaging settings page instructions.
// TRANS: [instant messages] is link text, "(%%doc.im%%)" is the link.
// TRANS: the order and formatting of link text and link should remain unchanged.
return _('You can send and receive notices through '. return _('You can send and receive notices through '.
'Jabber/GTalk [instant messages](%%doc.im%%). '. 'Jabber/GTalk [instant messages](%%doc.im%%). '.
'Configure your address and settings below.'); 'Configure your address and settings below.');
@ -86,6 +90,7 @@ class ImsettingsAction extends ConnectSettingsAction
{ {
if (!common_config('xmpp', 'enabled')) { if (!common_config('xmpp', 'enabled')) {
$this->element('div', array('class' => 'error'), $this->element('div', array('class' => 'error'),
// TRANS: Message given in the IM settings if XMPP is not enabled on the site.
_('IM is not available.')); _('IM is not available.'));
return; return;
} }
@ -97,32 +102,41 @@ class ImsettingsAction extends ConnectSettingsAction
'action' => 'action' =>
common_local_url('imsettings'))); common_local_url('imsettings')));
$this->elementStart('fieldset', array('id' => 'settings_im_address')); $this->elementStart('fieldset', array('id' => 'settings_im_address'));
$this->element('legend', null, _('Address')); // TRANS: Form legend for IM settings form.
$this->element('legend', null, _('IM address'));
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
if ($user->jabber) { if ($user->jabber) {
$this->element('p', 'form_confirmed', $user->jabber); $this->element('p', 'form_confirmed', $user->jabber);
// TRANS: Form note in IM settings form.
$this->element('p', 'form_note', $this->element('p', 'form_note',
_('Current confirmed Jabber/GTalk address.')); _('Current confirmed Jabber/GTalk address.'));
$this->hidden('jabber', $user->jabber); $this->hidden('jabber', $user->jabber);
$this->submit('remove', _('Remove')); // TRANS: Button label to remove a confirmed IM address.
$this->submit('remove', _m('BUTTON','Remove'));
} else { } else {
$confirm = $this->getConfirmation(); $confirm = $this->getConfirmation();
if ($confirm) { if ($confirm) {
$this->element('p', 'form_unconfirmed', $confirm->address); $this->element('p', 'form_unconfirmed', $confirm->address);
$this->element('p', 'form_note', $this->element('p', 'form_note',
// TRANS: Form note in IM settings form.
// TRANS: %s is the IM address set for the site.
sprintf(_('Awaiting confirmation on this address. '. sprintf(_('Awaiting confirmation on this address. '.
'Check your Jabber/GTalk account for a '. 'Check your Jabber/GTalk account for a '.
'message with further instructions. '. 'message with further instructions. '.
'(Did you add %s to your buddy list?)'), '(Did you add %s to your buddy list?)'),
jabber_daemon_address())); jabber_daemon_address()));
$this->hidden('jabber', $confirm->address); $this->hidden('jabber', $confirm->address);
$this->submit('cancel', _('Cancel')); // TRANS: Button label to cancel an IM address confirmation procedure.
$this->submit('cancel', _m('BUTTON','Cancel'));
} else { } else {
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Field label for IM address input in IM settings form.
$this->input('jabber', _('IM address'), $this->input('jabber', _('IM address'),
($this->arg('jabber')) ? $this->arg('jabber') : null, ($this->arg('jabber')) ? $this->arg('jabber') : null,
// TRANS: IM address input field instructions in IM settings form.
// TRANS: %s is the IM address set for the site.
sprintf(_('Jabber or GTalk address, '. sprintf(_('Jabber or GTalk address, '.
'like "UserName@example.org". '. 'like "UserName@example.org". '.
'First, make sure to add %s to your '. 'First, make sure to add %s to your '.
@ -130,37 +144,44 @@ class ImsettingsAction extends ConnectSettingsAction
jabber_daemon_address())); jabber_daemon_address()));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->submit('add', _('Add')); // TRANS: Button label for adding an IM address in IM settings form.
$this->submit('add', _m('BUTTON','Add'));
} }
} }
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementStart('fieldset', array('id' => 'settings_im_preferences')); $this->elementStart('fieldset', array('id' => 'settings_im_preferences'));
$this->element('legend', null, _('Preferences')); // TRANS: Form legend for IM preferences form.
$this->element('legend', null, _('IM preferences'));
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('jabbernotify', $this->checkbox('jabbernotify',
// TRANS: Checkbox label in IM preferences form.
_('Send me notices through Jabber/GTalk.'), _('Send me notices through Jabber/GTalk.'),
$user->jabbernotify); $user->jabbernotify);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('updatefrompresence', $this->checkbox('updatefrompresence',
// TRANS: Checkbox label in IM preferences form.
_('Post a notice when my Jabber/GTalk status changes.'), _('Post a notice when my Jabber/GTalk status changes.'),
$user->updatefrompresence); $user->updatefrompresence);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('jabberreplies', $this->checkbox('jabberreplies',
// TRANS: Checkbox label in IM preferences form.
_('Send me replies through Jabber/GTalk '. _('Send me replies through Jabber/GTalk '.
'from people I\'m not subscribed to.'), 'from people I\'m not subscribed to.'),
$user->jabberreplies); $user->jabberreplies);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('jabbermicroid', $this->checkbox('jabbermicroid',
// TRANS: Checkbox label in IM preferences form.
_('Publish a MicroID for my Jabber/GTalk address.'), _('Publish a MicroID for my Jabber/GTalk address.'),
$user->jabbermicroid); $user->jabbermicroid);
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->submit('save', _('Save')); // TRANS: Button label to save IM preferences.
$this->submit('save', _m('BUTTON','Save'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
} }
@ -217,6 +238,7 @@ class ImsettingsAction extends ConnectSettingsAction
} else if ($this->arg('remove')) { } else if ($this->arg('remove')) {
$this->removeAddress(); $this->removeAddress();
} else { } else {
// TRANS: Message given submitting a form with an unknown action in IM settings.
$this->showForm(_('Unexpected form submission.')); $this->showForm(_('Unexpected form submission.'));
} }
} }
@ -232,7 +254,6 @@ class ImsettingsAction extends ConnectSettingsAction
function savePreferences() function savePreferences()
{ {
$jabbernotify = $this->boolean('jabbernotify'); $jabbernotify = $this->boolean('jabbernotify');
$updatefrompresence = $this->boolean('updatefrompresence'); $updatefrompresence = $this->boolean('updatefrompresence');
$jabberreplies = $this->boolean('jabberreplies'); $jabberreplies = $this->boolean('jabberreplies');
@ -255,12 +276,14 @@ class ImsettingsAction extends ConnectSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error updating IM preferences.
$this->serverError(_('Couldn\'t update user.')); $this->serverError(_('Couldn\'t update user.'));
return; return;
} }
$user->query('COMMIT'); $user->query('COMMIT');
// TRANS: Confirmation message for successful IM preferences save.
$this->showForm(_('Preferences saved.'), true); $this->showForm(_('Preferences saved.'), true);
} }
@ -282,6 +305,7 @@ class ImsettingsAction extends ConnectSettingsAction
// Some validation // Some validation
if (!$jabber) { if (!$jabber) {
// TRANS: Message given saving IM address without having provided one.
$this->showForm(_('No Jabber ID.')); $this->showForm(_('No Jabber ID.'));
return; return;
} }
@ -289,16 +313,20 @@ class ImsettingsAction extends ConnectSettingsAction
$jabber = jabber_normalize_jid($jabber); $jabber = jabber_normalize_jid($jabber);
if (!$jabber) { if (!$jabber) {
// TRANS: Message given saving IM address that cannot be normalised.
$this->showForm(_('Cannot normalize that Jabber ID')); $this->showForm(_('Cannot normalize that Jabber ID'));
return; return;
} }
if (!jabber_valid_base_jid($jabber, common_config('email', 'domain_check'))) { if (!jabber_valid_base_jid($jabber, common_config('email', 'domain_check'))) {
// TRANS: Message given saving IM address that not valid.
$this->showForm(_('Not a valid Jabber ID')); $this->showForm(_('Not a valid Jabber ID'));
return; return;
} else if ($user->jabber == $jabber) { } else if ($user->jabber == $jabber) {
// TRANS: Message given saving IM address that is already set.
$this->showForm(_('That is already your Jabber ID.')); $this->showForm(_('That is already your Jabber ID.'));
return; return;
} else if ($this->jabberExists($jabber)) { } else if ($this->jabberExists($jabber)) {
// TRANS: Message given saving IM address that is already set for another user.
$this->showForm(_('Jabber ID already belongs to another user.')); $this->showForm(_('Jabber ID already belongs to another user.'));
return; return;
} }
@ -316,6 +344,7 @@ class ImsettingsAction extends ConnectSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($confirm, 'INSERT', __FILE__); common_log_db_error($confirm, 'INSERT', __FILE__);
// TRANS: Server error thrown on database error adding IM confirmation code.
$this->serverError(_('Couldn\'t insert confirmation code.')); $this->serverError(_('Couldn\'t insert confirmation code.'));
return; return;
} }
@ -324,6 +353,8 @@ class ImsettingsAction extends ConnectSettingsAction
$user->nickname, $user->nickname,
$jabber); $jabber);
// TRANS: Message given saving valid IM address that is to be confirmed.
// TRANS: %s is the IM address set for the site.
$msg = sprintf(_('A confirmation code was sent '. $msg = sprintf(_('A confirmation code was sent '.
'to the IM address you added. '. 'to the IM address you added. '.
'You must approve %s for '. 'You must approve %s for '.
@ -348,10 +379,12 @@ class ImsettingsAction extends ConnectSettingsAction
$confirm = $this->getConfirmation(); $confirm = $this->getConfirmation();
if (!$confirm) { if (!$confirm) {
// TRANS: Message given canceling IM address confirmation that is not pending.
$this->showForm(_('No pending confirmation to cancel.')); $this->showForm(_('No pending confirmation to cancel.'));
return; return;
} }
if ($confirm->address != $jabber) { if ($confirm->address != $jabber) {
// TRANS: Message given canceling IM address confirmation for the wrong IM address.
$this->showForm(_('That is the wrong IM address.')); $this->showForm(_('That is the wrong IM address.'));
return; return;
} }
@ -360,11 +393,13 @@ class ImsettingsAction extends ConnectSettingsAction
if (!$result) { if (!$result) {
common_log_db_error($confirm, 'DELETE', __FILE__); common_log_db_error($confirm, 'DELETE', __FILE__);
$this->serverError(_('Couldn\'t delete email confirmation.')); // TRANS: Server error thrown on database error canceling IM address confirmation.
$this->serverError(_('Couldn\'t delete IM confirmation.'));
return; return;
} }
$this->showForm(_('Confirmation cancelled.'), true); // TRANS: Message given after successfully canceling IM address confirmation.
$this->showForm(_('IM confirmation cancelled.'), true);
} }
/** /**
@ -384,6 +419,8 @@ class ImsettingsAction extends ConnectSettingsAction
// Maybe an old tab open...? // Maybe an old tab open...?
if ($user->jabber != $jabber) { if ($user->jabber != $jabber) {
// TRANS: Message given trying to remove an IM address that is not
// TRANS: registered for the active user.
$this->showForm(_('That is not your Jabber ID.')); $this->showForm(_('That is not your Jabber ID.'));
return; return;
} }
@ -398,6 +435,7 @@ class ImsettingsAction extends ConnectSettingsAction
if (!$result) { if (!$result) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error removing a registered IM address.
$this->serverError(_('Couldn\'t update user.')); $this->serverError(_('Couldn\'t update user.'));
return; return;
} }
@ -405,7 +443,8 @@ class ImsettingsAction extends ConnectSettingsAction
// XXX: unsubscribe to the old address // XXX: unsubscribe to the old address
$this->showForm(_('The address was removed.'), true); // TRANS: Message given after successfully removing a registered IM address.
$this->showForm(_('The IM address was removed.'), true);
} }
/** /**

View File

@ -224,8 +224,10 @@ class InviteAction extends CurrentUserDesignAction
$headers['From'] = mail_notify_from(); $headers['From'] = mail_notify_from();
$headers['To'] = trim($email); $headers['To'] = trim($email);
// TRANS: Subject for invitation email. Note that 'them' is correct as a gender-neutral singular 3rd-person pronoun in English.
$headers['Subject'] = sprintf(_('%1$s has invited you to join them on %2$s'), $bestname, $sitename); $headers['Subject'] = sprintf(_('%1$s has invited you to join them on %2$s'), $bestname, $sitename);
// TRANS: Body text for invitation email. Note that 'them' is correct as a gender-neutral singular 3rd-person pronoun in English.
$body = sprintf(_("%1\$s has invited you to join them on %2\$s (%3\$s).\n\n". $body = sprintf(_("%1\$s has invited you to join them on %2\$s (%3\$s).\n\n".
"%2\$s is a micro-blogging service that lets you keep up-to-date with people you know and people who interest you.\n\n". "%2\$s is a micro-blogging service that lets you keep up-to-date with people you know and people who interest you.\n\n".
"You can also share news about yourself, your thoughts, or your life online with people who know about you. ". "You can also share news about yourself, your thoughts, or your life online with people who know about you. ".

View File

@ -82,7 +82,7 @@ class NudgeAction extends Action
} }
if (!$other->email || !$other->emailnotifynudge) { if (!$other->email || !$other->emailnotifynudge) {
$this->clientError(_('This user doesn\'t allow nudges or hasn\'t confirmed or set his email yet.')); $this->clientError(_('This user doesn\'t allow nudges or hasn\'t confirmed or set their email yet.'));
return; return;
} }

View File

@ -23,6 +23,7 @@
* @package StatusNet * @package StatusNet
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@status.net>
* @copyright 2008 StatusNet, Inc. * @copyright 2008 StatusNet, Inc.
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @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/
*/ */

View File

@ -8,7 +8,9 @@
* @category Action * @category Action
* @package StatusNet * @package StatusNet
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@status.net>
* @author Craig Andrews <candrews@integralblue.com>
* @author Robin Millette <millette@status.net> * @author Robin Millette <millette@status.net>
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
* *
@ -44,6 +46,7 @@ require_once INSTALLDIR.'/lib/xrdsoutputter.php';
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@status.net>
* @author Robin Millette <millette@status.net> * @author Robin Millette <millette@status.net>
* @author Craig Andrews <candrews@integralblue.com> * @author Craig Andrews <candrews@integralblue.com>
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/ * @link http://status.net/
* *

View File

@ -348,7 +348,7 @@ class RegisterAction extends Action
} else { } else {
$instr = $instr =
common_markup_to_html(_('With this form you can create '. common_markup_to_html(_('With this form you can create '.
' a new account. ' . 'a new account. ' .
'You can then post notices and '. 'You can then post notices and '.
'link up to friends and colleagues. ')); 'link up to friends and colleagues. '));

View File

@ -196,18 +196,18 @@ class RepliesAction extends OwnerDesignAction
function showEmptyListMessage() function showEmptyListMessage()
{ {
$message = sprintf(_('This is the timeline showing replies to %1$s but %2$s hasn\'t received a notice to his attention yet.'), $this->user->nickname, $this->user->nickname) . ' '; $message = sprintf(_('This is the timeline showing replies to %1$s but %2$s hasn\'t received a notice to their attention yet.'), $this->user->nickname, $this->user->nickname) . ' ';
if (common_logged_in()) { if (common_logged_in()) {
$current_user = common_current_user(); $current_user = common_current_user();
if ($this->user->id === $current_user->id) { if ($this->user->id === $current_user->id) {
$message .= _('You can engage other users in a conversation, subscribe to more people or [join groups](%%action.groups%%).'); $message .= _('You can engage other users in a conversation, subscribe to more people or [join groups](%%action.groups%%).');
} else { } else {
$message .= sprintf(_('You can try to [nudge %1$s](../%2$s) or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname); $message .= sprintf(_('You can try to [nudge %1$s](../%2$s) or [post something to their attention](%%%%action.newnotice%%%%?status_textarea=%3$s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname);
} }
} }
else { else {
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname); $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to their attention.'), $this->user->nickname);
} }
$this->elementStart('div', 'guide'); $this->elementStart('div', 'guide');

View File

@ -119,7 +119,7 @@ class ShowfavoritesAction extends OwnerDesignAction
if (!empty($cur) && $cur->id == $this->user->id) { if (!empty($cur) && $cur->id == $this->user->id) {
// Show imported/gateway notices as well as local if // Show imported/gateway notices as well as local if
// the user is looking at his own favorites // the user is looking at their own favorites
$this->notice = $this->user->favoriteNotices(true, ($this->page-1)*NOTICES_PER_PAGE, $this->notice = $this->user->favoriteNotices(true, ($this->page-1)*NOTICES_PER_PAGE,
NOTICES_PER_PAGE + 1); NOTICES_PER_PAGE + 1);
@ -205,11 +205,11 @@ class ShowfavoritesAction extends OwnerDesignAction
if ($this->user->id === $current_user->id) { if ($this->user->id === $current_user->id) {
$message = _('You haven\'t chosen any favorite notices yet. Click the fave button on notices you like to bookmark them for later or shed a spotlight on them.'); $message = _('You haven\'t chosen any favorite notices yet. Click the fave button on notices you like to bookmark them for later or shed a spotlight on them.');
} else { } else {
$message = sprintf(_('%s hasn\'t added any notices to his favorites yet. Post something interesting they would add to their favorites :)'), $this->user->nickname); $message = sprintf(_('%s hasn\'t added any favorite notices yet. Post something interesting they would add to their favorites :)'), $this->user->nickname);
} }
} }
else { else {
$message = sprintf(_('%s hasn\'t added any notices to his favorites yet. Why not [register an account](%%%%action.register%%%%) and then post something interesting they would add to their favorites :)'), $this->user->nickname); $message = sprintf(_('%s hasn\'t added any favorite notices yet. Why not [register an account](%%%%action.register%%%%) and then post something interesting they would add to their favorites :)'), $this->user->nickname);
} }
$this->elementStart('div', 'guide'); $this->elementStart('div', 'guide');

View File

@ -430,14 +430,6 @@ class ShowgroupAction extends GroupDesignAction
function showStatistics() function showStatistics()
{ {
// XXX: WORM cache this
$members = $this->group->getMembers();
$members_count = 0;
/** $member->count() doesn't work. */
while ($members->fetch()) {
$members_count++;
}
$this->elementStart('div', array('id' => 'entity_statistics', $this->elementStart('div', array('id' => 'entity_statistics',
'class' => 'section')); 'class' => 'section'));
@ -451,7 +443,7 @@ class ShowgroupAction extends GroupDesignAction
$this->elementStart('dl', 'entity_members'); $this->elementStart('dl', 'entity_members');
$this->element('dt', null, _('Members')); $this->element('dt', null, _('Members'));
$this->element('dd', null, (is_int($members_count)) ? $members_count : '0'); $this->element('dd', null, $this->group->getMemberCount());
$this->elementEnd('dl'); $this->elementEnd('dl');
$this->elementEnd('div'); $this->elementEnd('div');

View File

@ -167,7 +167,7 @@ class ShownoticeAction extends OwnerDesignAction
function title() function title()
{ {
if (!empty($this->profile->fullname)) { if (!empty($this->profile->fullname)) {
$base = $this->profile->fullname . ' (' . $this->profile->nickname . ') '; $base = $this->profile->fullname . ' (' . $this->profile->nickname . ')';
} else { } else {
$base = $this->profile->nickname; $base = $this->profile->nickname;
} }

View File

@ -204,11 +204,11 @@ class ShowstreamAction extends ProfileAction
if ($this->user->id === $current_user->id) { if ($this->user->id === $current_user->id) {
$message .= _('Seen anything interesting recently? You haven\'t posted any notices yet, now would be a good time to start :)'); $message .= _('Seen anything interesting recently? You haven\'t posted any notices yet, now would be a good time to start :)');
} else { } else {
$message .= sprintf(_('You can try to nudge %1$s or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%2$s).'), $this->user->nickname, '@' . $this->user->nickname); $message .= sprintf(_('You can try to nudge %1$s or [post something to their attention](%%%%action.newnotice%%%%?status_textarea=%2$s).'), $this->user->nickname, '@' . $this->user->nickname);
} }
} }
else { else {
$message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname); $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to their attention.'), $this->user->nickname);
} }
$this->elementStart('div', 'guide'); $this->elementStart('div', 'guide');

View File

@ -55,6 +55,7 @@ class SmssettingsAction extends ConnectSettingsAction
function title() function title()
{ {
// TRANS: Title for SMS settings.
return _('SMS settings'); return _('SMS settings');
} }
@ -66,6 +67,10 @@ class SmssettingsAction extends ConnectSettingsAction
function getInstructions() function getInstructions()
{ {
// XXX: For consistency of parameters in messages, this should be a
// regular parameters, replaced with sprintf().
// TRANS: SMS settings page instructions.
// TRANS: %%site.name%% is the name of the site.
return _('You can receive SMS messages through email from %%site.name%%.'); return _('You can receive SMS messages through email from %%site.name%%.');
} }
@ -88,6 +93,7 @@ class SmssettingsAction extends ConnectSettingsAction
{ {
if (!common_config('sms', 'enabled')) { if (!common_config('sms', 'enabled')) {
$this->element('div', array('class' => 'error'), $this->element('div', array('class' => 'error'),
// TRANS: Message given in the SMS settings if SMS is not enabled on the site.
_('SMS is not available.')); _('SMS is not available.'));
return; return;
} }
@ -101,7 +107,8 @@ class SmssettingsAction extends ConnectSettingsAction
common_local_url('smssettings'))); common_local_url('smssettings')));
$this->elementStart('fieldset', array('id' => 'settings_sms_address')); $this->elementStart('fieldset', array('id' => 'settings_sms_address'));
$this->element('legend', null, _('Address')); // TRANS: Form legend for SMS settings form.
$this->element('legend', null, _('SMS address'));
$this->hidden('token', common_session_token()); $this->hidden('token', common_session_token());
if ($user->sms) { if ($user->sms) {
@ -109,10 +116,12 @@ class SmssettingsAction extends ConnectSettingsAction
$this->element('p', 'form_confirmed', $this->element('p', 'form_confirmed',
$user->sms . ' (' . $carrier->name . ')'); $user->sms . ' (' . $carrier->name . ')');
$this->element('p', 'form_guide', $this->element('p', 'form_guide',
// TRANS: Form guide in SMS settings form.
_('Current confirmed SMS-enabled phone number.')); _('Current confirmed SMS-enabled phone number.'));
$this->hidden('sms', $user->sms); $this->hidden('sms', $user->sms);
$this->hidden('carrier', $user->carrier); $this->hidden('carrier', $user->carrier);
$this->submit('remove', _('Remove')); // TRANS: Button label to remove a confirmed SMS address.
$this->submit('remove', _m('BUTTON','Remove'));
} else { } else {
$confirm = $this->getConfirmation(); $confirm = $this->getConfirmation();
if ($confirm) { if ($confirm) {
@ -120,57 +129,75 @@ class SmssettingsAction extends ConnectSettingsAction
$this->element('p', 'form_unconfirmed', $this->element('p', 'form_unconfirmed',
$confirm->address . ' (' . $carrier->name . ')'); $confirm->address . ' (' . $carrier->name . ')');
$this->element('p', 'form_guide', $this->element('p', 'form_guide',
// TRANS: Form guide in IM settings form.
_('Awaiting confirmation on this phone number.')); _('Awaiting confirmation on this phone number.'));
$this->hidden('sms', $confirm->address); $this->hidden('sms', $confirm->address);
$this->hidden('carrier', $confirm->address_extra); $this->hidden('carrier', $confirm->address_extra);
$this->submit('cancel', _('Cancel')); // TRANS: Button label to cancel a SMS address confirmation procedure.
$this->submit('cancel', _m('BUTTON','Cancel'));
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Field label for SMS address input in SMS settings form.
$this->input('code', _('Confirmation code'), null, $this->input('code', _('Confirmation code'), null,
// TRANS: Form field instructions in SMS settings form.
_('Enter the code you received on your phone.')); _('Enter the code you received on your phone.'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->submit('confirm', _('Confirm')); // TRANS: Button label to confirm SMS confirmation code in SMS settings.
$this->submit('confirm', _m('BUTTON','Confirm'));
} else { } else {
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Field label for SMS phone number input in SMS settings form.
$this->input('sms', _('SMS phone number'), $this->input('sms', _('SMS phone number'),
($this->arg('sms')) ? $this->arg('sms') : null, ($this->arg('sms')) ? $this->arg('sms') : null,
// TRANS: SMS phone number input field instructions in SMS settings form.
_('Phone number, no punctuation or spaces, '. _('Phone number, no punctuation or spaces, '.
'with area code')); 'with area code'));
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->carrierSelect(); $this->carrierSelect();
$this->submit('add', _('Add')); // TRANS: Button label for adding a SMS phone number in SMS settings form.
$this->submit('add', _m('BUTTON','Add'));
} }
} }
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
if ($user->sms) { if ($user->sms) {
$this->elementStart('fieldset', array('id' => 'settings_sms_incoming_email')); $this->elementStart('fieldset', array('id' => 'settings_sms_incoming_email'));
// XXX: Confused! This is about SMS. Should this message be updated?
// TRANS: Form legend for incoming SMS settings form.
$this->element('legend', null, _('Incoming email')); $this->element('legend', null, _('Incoming email'));
if ($user->incomingemail) { if ($user->incomingemail) {
$this->element('p', 'form_unconfirmed', $user->incomingemail); $this->element('p', 'form_unconfirmed', $user->incomingemail);
$this->element('p', 'form_note', $this->element('p', 'form_note',
// XXX: Confused! This is about SMS. Should this message be updated?
// TRANS: Form instructions for incoming SMS e-mail address form in SMS settings.
_('Send email to this address to post new notices.')); _('Send email to this address to post new notices.'));
$this->submit('removeincoming', _('Remove')); // TRANS: Button label for removing a set sender SMS e-mail address to post notices from.
$this->submit('removeincoming', _m('BUTTON','Remove'));
} }
$this->element('p', 'form_guide', $this->element('p', 'form_guide',
// XXX: Confused! This is about SMS. Should this message be updated?
// TRANS: Instructions for incoming SMS e-mail address input form.
_('Make a new email address for posting to; '. _('Make a new email address for posting to; '.
'cancels the old one.')); 'cancels the old one.'));
$this->submit('newincoming', _('New')); // TRANS: Button label for adding an SMS e-mail address to send notices from.
$this->submit('newincoming', _m('BUTTON','New'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
} }
$this->elementStart('fieldset', array('id' => 'settings_sms_preferences')); $this->elementStart('fieldset', array('id' => 'settings_sms_preferences'));
$this->element('legend', null, _('Preferences')); // TRANS: Form legend for SMS preferences form.
$this->element('legend', null, _('SMS preferences'));
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
$this->checkbox('smsnotify', $this->checkbox('smsnotify',
// TRANS: Checkbox label in SMS preferences form.
_('Send me notices through SMS; '. _('Send me notices through SMS; '.
'I understand I may incur '. 'I understand I may incur '.
'exorbitant charges from my carrier.'), 'exorbitant charges from my carrier.'),
@ -178,7 +205,8 @@ class SmssettingsAction extends ConnectSettingsAction
$this->elementEnd('li'); $this->elementEnd('li');
$this->elementEnd('ul'); $this->elementEnd('ul');
$this->submit('save', _('Save')); // TRANS: Button label to save SMS preferences.
$this->submit('save', _m('BUTTON','Save'));
$this->elementEnd('fieldset'); $this->elementEnd('fieldset');
$this->elementEnd('form'); $this->elementEnd('form');
@ -245,6 +273,7 @@ class SmssettingsAction extends ConnectSettingsAction
} else if ($this->arg('confirm')) { } else if ($this->arg('confirm')) {
$this->confirmCode(); $this->confirmCode();
} else { } else {
// TRANS: Message given submitting a form with an unknown action in SMS settings.
$this->showForm(_('Unexpected form submission.')); $this->showForm(_('Unexpected form submission.'));
} }
} }
@ -275,13 +304,15 @@ class SmssettingsAction extends ConnectSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error updating SMS preferences.
$this->serverError(_('Couldn\'t update user.')); $this->serverError(_('Couldn\'t update user.'));
return; return;
} }
$user->query('COMMIT'); $user->query('COMMIT');
$this->showForm(_('Preferences saved.'), true); // TRANS: Confirmation message for successful SMS preferences save.
$this->showForm(_('SMS preferences saved.'), true);
} }
/** /**
@ -303,11 +334,13 @@ class SmssettingsAction extends ConnectSettingsAction
// Some validation // Some validation
if (!$sms) { if (!$sms) {
// TRANS: Message given saving SMS phone number without having provided one.
$this->showForm(_('No phone number.')); $this->showForm(_('No phone number.'));
return; return;
} }
if (!$carrier_id) { if (!$carrier_id) {
// TRANS: Message given saving SMS phone number without having selected a carrier.
$this->showForm(_('No carrier selected.')); $this->showForm(_('No carrier selected.'));
return; return;
} }
@ -315,9 +348,11 @@ class SmssettingsAction extends ConnectSettingsAction
$sms = common_canonical_sms($sms); $sms = common_canonical_sms($sms);
if ($user->sms == $sms) { if ($user->sms == $sms) {
// TRANS: Message given saving SMS phone number that is already set.
$this->showForm(_('That is already your phone number.')); $this->showForm(_('That is already your phone number.'));
return; return;
} else if ($this->smsExists($sms)) { } else if ($this->smsExists($sms)) {
// TRANS: Message given saving SMS phone number that is already set for another user.
$this->showForm(_('That phone number already belongs to another user.')); $this->showForm(_('That phone number already belongs to another user.'));
return; return;
} }
@ -334,6 +369,7 @@ class SmssettingsAction extends ConnectSettingsAction
if ($result === false) { if ($result === false) {
common_log_db_error($confirm, 'INSERT', __FILE__); common_log_db_error($confirm, 'INSERT', __FILE__);
// TRANS: Server error thrown on database error adding SMS confirmation code.
$this->serverError(_('Couldn\'t insert confirmation code.')); $this->serverError(_('Couldn\'t insert confirmation code.'));
return; return;
} }
@ -344,6 +380,7 @@ class SmssettingsAction extends ConnectSettingsAction
$user->nickname, $user->nickname,
$carrier->toEmailAddress($sms)); $carrier->toEmailAddress($sms));
// TRANS: Message given saving valid SMS phone number that is to be confirmed.
$msg = _('A confirmation code was sent to the phone number you added. '. $msg = _('A confirmation code was sent to the phone number you added. '.
'Check your phone for the code and instructions '. 'Check your phone for the code and instructions '.
'on how to use it.'); 'on how to use it.');
@ -367,10 +404,12 @@ class SmssettingsAction extends ConnectSettingsAction
$confirm = $this->getConfirmation(); $confirm = $this->getConfirmation();
if (!$confirm) { if (!$confirm) {
// TRANS: Message given canceling SMS phone number confirmation that is not pending.
$this->showForm(_('No pending confirmation to cancel.')); $this->showForm(_('No pending confirmation to cancel.'));
return; return;
} }
if ($confirm->address != $sms) { if ($confirm->address != $sms) {
// TRANS: Message given canceling SMS phone number confirmation for the wrong phone number.
$this->showForm(_('That is the wrong confirmation number.')); $this->showForm(_('That is the wrong confirmation number.'));
return; return;
} }
@ -379,11 +418,13 @@ class SmssettingsAction extends ConnectSettingsAction
if (!$result) { if (!$result) {
common_log_db_error($confirm, 'DELETE', __FILE__); common_log_db_error($confirm, 'DELETE', __FILE__);
// TRANS: Server error thrown on database error canceling SMS phone number confirmation.
$this->serverError(_('Couldn\'t delete email confirmation.')); $this->serverError(_('Couldn\'t delete email confirmation.'));
return; return;
} }
$this->showForm(_('Confirmation cancelled.'), true); // TRANS: Message given after successfully canceling SMS phone number confirmation.
$this->showForm(_('SMS confirmation cancelled.'), true);
} }
/** /**
@ -402,6 +443,8 @@ class SmssettingsAction extends ConnectSettingsAction
// Maybe an old tab open...? // Maybe an old tab open...?
if ($user->sms != $sms) { if ($user->sms != $sms) {
// TRANS: Message given trying to remove an SMS phone number that is not
// TRANS: registered for the active user.
$this->showForm(_('That is not your phone number.')); $this->showForm(_('That is not your phone number.'));
return; return;
} }
@ -417,12 +460,14 @@ class SmssettingsAction extends ConnectSettingsAction
$result = $user->updateKeys($original); $result = $user->updateKeys($original);
if (!$result) { if (!$result) {
common_log_db_error($user, 'UPDATE', __FILE__); common_log_db_error($user, 'UPDATE', __FILE__);
// TRANS: Server error thrown on database error removing a registered SMS phone number.
$this->serverError(_('Couldn\'t update user.')); $this->serverError(_('Couldn\'t update user.'));
return; return;
} }
$user->query('COMMIT'); $user->query('COMMIT');
$this->showForm(_('The address was removed.'), true); // TRANS: Message given after successfully removing a registered SMS phone number.
$this->showForm(_('The SMS phone number was removed.'), true);
} }
/** /**
@ -462,10 +507,12 @@ class SmssettingsAction extends ConnectSettingsAction
$this->elementStart('ul', 'form_data'); $this->elementStart('ul', 'form_data');
$this->elementStart('li'); $this->elementStart('li');
// TRANS: Label for mobile carrier dropdown menu in SMS settings.
$this->element('label', array('for' => 'carrier'), _('Mobile carrier')); $this->element('label', array('for' => 'carrier'), _('Mobile carrier'));
$this->elementStart('select', array('name' => 'carrier', $this->elementStart('select', array('name' => 'carrier',
'id' => 'carrier')); 'id' => 'carrier'));
$this->element('option', array('value' => 0), $this->element('option', array('value' => 0),
// TRANS: Default option for mobile carrier dropdown menu in SMS settings.
_('Select a carrier')); _('Select a carrier'));
while ($carrier->fetch()) { while ($carrier->fetch()) {
$this->element('option', array('value' => $carrier->id), $this->element('option', array('value' => $carrier->id),
@ -473,6 +520,8 @@ class SmssettingsAction extends ConnectSettingsAction
} }
$this->elementEnd('select'); $this->elementEnd('select');
$this->element('p', 'form_guide', $this->element('p', 'form_guide',
// TRANS: Form instructions for mobile carrier dropdown menu in SMS settings.
// TRANS: %s is an administrative contact's e-mail address.
sprintf(_('Mobile carrier for your phone. '. sprintf(_('Mobile carrier for your phone. '.
'If you know a carrier that accepts ' . 'If you know a carrier that accepts ' .
'SMS over email but isn\'t listed here, ' . 'SMS over email but isn\'t listed here, ' .
@ -495,6 +544,7 @@ class SmssettingsAction extends ConnectSettingsAction
$code = $this->trimmed('code'); $code = $this->trimmed('code');
if (!$code) { if (!$code) {
// TRANS: Message given saving SMS phone number confirmation code without having provided one.
$this->showForm(_('No code entered')); $this->showForm(_('No code entered'));
return; return;
} }

View File

@ -197,7 +197,7 @@ class SnapshotAdminPanelForm extends AdminForm
$this->out->elementStart('ul', 'form_data'); $this->out->elementStart('ul', 'form_data');
$this->li(); $this->li();
$snapshot = array( $snapshot = array(
'web' => _('Randomly during Web hit'), 'web' => _('Randomly during web hit'),
'cron' => _('In a scheduled job'), 'cron' => _('In a scheduled job'),
'never' => _('Never') 'never' => _('Never')
); );

View File

@ -102,12 +102,17 @@ class TagAction extends Action
function showContent() function showContent()
{ {
if(Event::handle('StartTagShowContent', array($this))) {
$nl = new NoticeList($this->notice, $this); $nl = new NoticeList($this->notice, $this);
$cnt = $nl->show(); $cnt = $nl->show();
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE, $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
$this->page, 'tag', array('tag' => $this->tag)); $this->page, 'tag', array('tag' => $this->tag));
Event::handle('EndTagShowContent', array($this));
}
} }
function isReadOnly($args) function isReadOnly($args)

View File

@ -59,8 +59,10 @@ class UsergroupsAction extends OwnerDesignAction
function title() function title()
{ {
if ($this->page == 1) { if ($this->page == 1) {
// TRANS: Message is used as a page title. %s is a nick name.
return sprintf(_('%s groups'), $this->user->nickname); return sprintf(_('%s groups'), $this->user->nickname);
} else { } else {
// TRANS: Message is used as a page title. %1$s is a nick name, %2$d is a page number.
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);

View File

@ -72,7 +72,7 @@ class UserrssAction extends Rss10Action
{ {
$notice = $this->user->getNotices( $notice = $this->user->getNotices(
0, 0,
($limit == 0) ? NOTICES_PER_PAGE : $limit ($this->limit == 0) ? NOTICES_PER_PAGE : $this->limit
); );
$notices = array(); $notices = array();
@ -90,8 +90,10 @@ class UserrssAction extends Rss10Action
$c = array('url' => common_local_url('userrss', $c = array('url' => common_local_url('userrss',
array('nickname' => array('nickname' =>
$user->nickname)), $user->nickname)),
// TRANS: Message is used as link title. %s is a user nickname.
'title' => sprintf(_('%s timeline'), $user->nickname), 'title' => sprintf(_('%s timeline'), $user->nickname),
'link' => $profile->profileurl, 'link' => $profile->profileurl,
// TRANS: Message is used as link description. %1$s is a username, %2$s is a site name.
'description' => sprintf(_('Updates from %1$s on %2$s!'), 'description' => sprintf(_('Updates from %1$s on %2$s!'),
$user->nickname, common_config('site', 'name'))); $user->nickname, common_config('site', 'name')));
return $c; return $c;

View File

@ -41,6 +41,8 @@ if (!defined('STATUSNET')) {
* @category Info * @category Info
* @package StatusNet * @package StatusNet
* @author Evan Prodromou <evan@status.net> * @author Evan Prodromou <evan@status.net>
* @author Craig Andrews <candrews@integralblue.com>
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
* @link http://status.net/ * @link http://status.net/
*/ */

View File

@ -302,7 +302,10 @@ class File extends Memcached_DataObject
if(! isset($this->filename)){ if(! isset($this->filename)){
$notEnclosureMimeTypes = array(null,'text/html','application/xhtml+xml'); $notEnclosureMimeTypes = array(null,'text/html','application/xhtml+xml');
$mimetype = $this->mimetype;
if($mimetype != null){
$mimetype = strtolower($this->mimetype); $mimetype = strtolower($this->mimetype);
}
$semicolon = strpos($mimetype,';'); $semicolon = strpos($mimetype,';');
if($semicolon){ if($semicolon){
$mimetype = substr($mimetype,0,$semicolon); $mimetype = substr($mimetype,0,$semicolon);

View File

@ -39,6 +39,22 @@ class Foreign_user extends Memcached_DataObject
return null; return null;
} }
static function getByNickname($nickname, $service)
{
if (empty($nickname) || empty($service)) {
return null;
} else {
$fuser = new Foreign_user();
$fuser->service = $service;
$fuser->nickname = $nickname;
$fuser->limit(1);
$result = $fuser->find(true);
return empty($result) ? null : $fuser;
}
}
function updateKeys(&$orig) function updateKeys(&$orig)
{ {
$this->_connect(); $this->_connect();

View File

@ -115,9 +115,12 @@ class Inbox extends Memcached_DataObject
*/ */
static function insertNotice($user_id, $notice_id) static function insertNotice($user_id, $notice_id)
{ {
$inbox = DB_DataObject::staticGet('inbox', 'user_id', $user_id); // Going straight to the DB rather than trusting our caching
// during an update. Note: not using DB_DataObject::staticGet,
if (empty($inbox)) { // which is unsafe to use directly (in-process caching causes
// memory leaks, which accumulate in queue processes).
$inbox = new Inbox();
if (!$inbox->get('user_id', $user_id)) {
$inbox = Inbox::initialize($user_id); $inbox = Inbox::initialize($user_id);
} }

View File

@ -128,12 +128,13 @@ class Memcached_DataObject extends Safe_DataObject
} }
static function cacheKey($cls, $k, $v) { static function cacheKey($cls, $k, $v) {
if (is_object($cls) || is_object($k) || is_object($v)) { if (is_object($cls) || is_object($k) || (is_object($v) && !($v instanceof DB_DataObject_Cast))) {
$e = new Exception(); $e = new Exception();
common_log(LOG_ERR, __METHOD__ . ' object in param: ' . common_log(LOG_ERR, __METHOD__ . ' object in param: ' .
str_replace("\n", " ", $e->getTraceAsString())); str_replace("\n", " ", $e->getTraceAsString()));
} }
return common_cache_key(strtolower($cls).':'.$k.':'.$v); $vstr = self::valueString($v);
return common_cache_key(strtolower($cls).':'.$k.':'.$vstr);
} }
static function getcached($cls, $k, $v) { static function getcached($cls, $k, $v) {
@ -229,10 +230,10 @@ class Memcached_DataObject extends Safe_DataObject
if (empty($this->$key)) { if (empty($this->$key)) {
continue; continue;
} }
$ckeys[] = $this->cacheKey($this->tableName(), $key, $this->$key); $ckeys[] = $this->cacheKey($this->tableName(), $key, self::valueString($this->$key));
} else if ($type == 'K' || $type == 'N') { } else if ($type == 'K' || $type == 'N') {
$pkey[] = $key; $pkey[] = $key;
$pval[] = $this->$key; $pval[] = self::valueString($this->$key);
} else { } else {
throw new Exception("Unknown key type $key => $type for " . $this->tableName()); throw new Exception("Unknown key type $key => $type for " . $this->tableName());
} }
@ -592,7 +593,7 @@ class Memcached_DataObject extends Safe_DataObject
return $c->get($cacheKey); return $c->get($cacheKey);
} }
static function cacheSet($keyPart, $value) static function cacheSet($keyPart, $value, $flag=null, $expiry=null)
{ {
$c = self::memcache(); $c = self::memcache();
@ -602,7 +603,32 @@ class Memcached_DataObject extends Safe_DataObject
$cacheKey = common_cache_key($keyPart); $cacheKey = common_cache_key($keyPart);
return $c->set($cacheKey, $value); return $c->set($cacheKey, $value, $flag, $expiry);
}
static function valueString($v)
{
$vstr = null;
if (is_object($v) && $v instanceof DB_DataObject_Cast) {
switch ($v->type) {
case 'date':
$vstr = $v->year . '-' . $v->month . '-' . $v->day;
break;
case 'blob':
case 'string':
case 'sql':
case 'datetime':
case 'time':
throw new ServerException("Unhandled DB_DataObject_Cast type passed as cacheKey value: '$v->type'");
break;
default:
throw new ServerException("Unknown DB_DataObject_Cast type passed as cacheKey value: '$v->type'");
break;
}
} else {
$vstr = strval($v);
}
return $vstr;
} }
} }

View File

@ -29,6 +29,7 @@
* @author Robin Millette <millette@controlyourself.ca> * @author Robin Millette <millette@controlyourself.ca>
* @author Sarven Capadisli <csarven@controlyourself.ca> * @author Sarven Capadisli <csarven@controlyourself.ca>
* @author Tom Adams <tom@holizz.com> * @author Tom Adams <tom@holizz.com>
* @copyright 2009 Free Software Foundation, Inc http://www.fsf.org
* @license GNU Affero General Public License http://www.gnu.org/licenses/ * @license GNU Affero General Public License http://www.gnu.org/licenses/
*/ */
@ -41,10 +42,10 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
*/ */
require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
/* We keep the first three 20-notice pages, plus one for pagination check, /* We keep 200 notices, the max number of notices available per API request,
* in the memcached cache. */ * in the memcached cache. */
define('NOTICE_CACHE_WINDOW', 61); define('NOTICE_CACHE_WINDOW', 200);
define('MAX_BOXCARS', 128); define('MAX_BOXCARS', 128);
@ -89,7 +90,13 @@ class Notice extends Memcached_DataObject
function getProfile() function getProfile()
{ {
return Profile::staticGet('id', $this->profile_id); $profile = Profile::staticGet('id', $this->profile_id);
if (empty($profile)) {
throw new ServerException(sprintf(_('No such profile (%d) for notice (%d)'), $this->profile_id, $this->id));
}
return $profile;
} }
function delete() function delete()
@ -177,7 +184,8 @@ class Notice extends Memcached_DataObject
$id = $tag->insert(); $id = $tag->insert();
if (!$id) { if (!$id) {
throw new ServerException(sprintf(_('DB error inserting hashtag: %s'), // TRANS: Server exception. %s are the error details.
throw new ServerException(sprintf(_('Database error inserting hashtag: %s'),
$last_error->message)); $last_error->message));
return; return;
} }
@ -267,7 +275,7 @@ class Notice extends Memcached_DataObject
if (!$profile->hasRight(Right::NEWNOTICE)) { if (!$profile->hasRight(Right::NEWNOTICE)) {
common_log(LOG_WARNING, "Attempted post from user disallowed to post: " . $profile->nickname); common_log(LOG_WARNING, "Attempted post from user disallowed to post: " . $profile->nickname);
throw new ClientException(_('You are banned from posting notices on this site.')); throw new ClientException(_('You are banned from posting notices on this site.'), 403);
} }
$notice = new Notice(); $notice = new Notice();
@ -1190,7 +1198,7 @@ class Notice extends Memcached_DataObject
'xmlns:media' => 'http://purl.org/syndication/atommedia', 'xmlns:media' => 'http://purl.org/syndication/atommedia',
'xmlns:poco' => 'http://portablecontacts.net/spec/1.0', 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0',
'xmlns:ostatus' => 'http://ostatus.org/schema/1.0', 'xmlns:ostatus' => 'http://ostatus.org/schema/1.0',
'xmlns:statusnet' => 'http://status.net/ont/'); 'xmlns:statusnet' => 'http://status.net/schema/api/1/');
} else { } else {
$attrs = array(); $attrs = array();
} }
@ -1225,7 +1233,7 @@ class Notice extends Memcached_DataObject
$xs->element('title', null, common_xml_safe_str($this->content)); $xs->element('title', null, common_xml_safe_str($this->content));
if ($author) { if ($author) {
$xs->raw($profile->asAtomAuthor()); $xs->raw($profile->asAtomAuthor($cur));
$xs->raw($profile->asActivityActor()); $xs->raw($profile->asActivityActor());
} }
@ -1238,9 +1246,25 @@ class Notice extends Memcached_DataObject
$xs->element('published', null, common_date_w3dtf($this->created)); $xs->element('published', null, common_date_w3dtf($this->created));
$xs->element('updated', null, common_date_w3dtf($this->created)); $xs->element('updated', null, common_date_w3dtf($this->created));
$source = null;
$ns = $this->getSource();
if ($ns) {
if (!empty($ns->name) && !empty($ns->url)) {
$source = '<a href="'
. htmlspecialchars($ns->url)
. '" rel="nofollow">'
. htmlspecialchars($ns->name)
. '</a>';
} else {
$source = $ns->code;
}
}
$noticeInfoAttr = array( $noticeInfoAttr = array(
'local_id' => $this->id, // local notice ID (useful to clients for ordering) 'local_id' => $this->id, // local notice ID (useful to clients for ordering)
'source' => $this->source, // the client name (source attribution) 'source' => $source, // the client name (source attribution)
); );
$ns = $this->getSource(); $ns = $this->getSource();
@ -1252,6 +1276,8 @@ class Notice extends Memcached_DataObject
if (!empty($cur)) { if (!empty($cur)) {
$noticeInfoAttr['favorite'] = ($cur->hasFave($this)) ? "true" : "false"; $noticeInfoAttr['favorite'] = ($cur->hasFave($this)) ? "true" : "false";
$profile = $cur->getProfile();
$noticeInfoAttr['repeated'] = ($profile->hasRepeated($this->id)) ? "true" : "false";
} }
if (!empty($this->repeat_of)) { if (!empty($this->repeat_of)) {
@ -1555,6 +1581,8 @@ class Notice extends Memcached_DataObject
{ {
$author = Profile::staticGet('id', $this->profile_id); $author = Profile::staticGet('id', $this->profile_id);
// TRANS: Message used to repeat a notice. RT is the abbreviation of 'retweet'.
// TRANS: %1$s is the repeated user's name, %2$s is the repeated notice.
$content = sprintf(_('RT @%1$s %2$s'), $content = sprintf(_('RT @%1$s %2$s'),
$author->nickname, $author->nickname,
$this->content); $this->content);
@ -1861,4 +1889,16 @@ class Notice extends Memcached_DataObject
return $ns; return $ns;
} }
/**
* Determine whether the notice was locally created
*
* @return boolean locality
*/
public function isLocal()
{
return ($this->is_local == Notice::LOCAL_PUBLIC ||
$this->is_local == Notice::LOCAL_NONPUBLIC);
}
} }

View File

@ -849,15 +849,23 @@ class Profile extends Memcached_DataObject
* *
* Assumes that Atom has been previously set up as the base namespace. * Assumes that Atom has been previously set up as the base namespace.
* *
* @param Profile $cur the current authenticated user
*
* @return string * @return string
*/ */
function asAtomAuthor() function asAtomAuthor($cur = null)
{ {
$xs = new XMLStringer(true); $xs = new XMLStringer(true);
$xs->elementStart('author'); $xs->elementStart('author');
$xs->element('name', null, $this->nickname); $xs->element('name', null, $this->nickname);
$xs->element('uri', null, $this->getUri()); $xs->element('uri', null, $this->getUri());
if ($cur != null) {
$attrs = Array();
$attrs['following'] = $cur->isSubscribed($this) ? 'true' : 'false';
$attrs['blocking'] = $cur->hasBlocked($this) ? 'true' : 'false';
$xs->element('statusnet:profile_info', $attrs, null);
}
$xs->elementEnd('author'); $xs->elementEnd('author');
return $xs->getString(); return $xs->getString();

View File

@ -64,4 +64,17 @@ class Queue_item extends Memcached_DataObject
$qi = null; $qi = null;
return null; return null;
} }
/**
* Release a claimed item.
*/
function releaseCLaim()
{
// DB_DataObject doesn't let us save nulls right now
$sql = sprintf("UPDATE queue_item SET claimed=NULL WHERE id=%d", $this->id);
$this->query($sql);
$this->claimed = null;
$this->encache();
}
} }

View File

@ -96,6 +96,30 @@ class Safe_DataObject extends DB_DataObject
$this->_link_loaded = false; $this->_link_loaded = false;
} }
/**
* Magic function called when someone attempts to call a method
* that doesn't exist. DB_DataObject uses this to implement
* setters and getters for fields, but neglects to throw an error
* when you just misspell an actual method name. This leads to
* silent failures which can cause all kinds of havoc.
*
* @param string $method
* @param array $params
* @return mixed
* @throws Exception
*/
function __call($method, $params)
{
$return = null;
// Yes, that's _call with one underscore, which does the
// actual implementation.
if ($this->_call($method, $params, $return)) {
return $return;
} else {
throw new Exception('Call to undefined method ' .
get_class($this) . '::' . $method);
}
}
/** /**
* Work around memory-leak bugs... * Work around memory-leak bugs...

View File

@ -144,6 +144,35 @@ class Status_network extends Safe_DataObject
return parent::update($orig); return parent::update($orig);
} }
/**
* DB_DataObject doesn't allow updating keys (even non-primary)
*/
function updateKeys(&$orig)
{
$this->_connect();
foreach (array('hostname', 'pathname') as $k) {
if (strcmp($this->$k, $orig->$k) != 0) {
$parts[] = $k . ' = ' . $this->_quote($this->$k);
}
}
if (count($parts) == 0) {
// No changes
return true;
}
$toupdate = implode(', ', $parts);
$table = common_database_tablename($this->tableName());
$qry = 'UPDATE ' . $table . ' SET ' . $toupdate .
' WHERE nickname = ' . $this->_quote($this->nickname);
$orig->decache();
$result = $this->query($qry);
if ($result) {
$this->encache();
}
return $result;
}
function delete() function delete()
{ {
$this->decache(); # while we still have the values! $this->decache(); # while we still have the values!
@ -152,18 +181,12 @@ class Status_network extends Safe_DataObject
/** /**
* @param string $servername hostname * @param string $servername hostname
* @param string $pathname URL base path
* @param string $wildcard hostname suffix to match wildcard config * @param string $wildcard hostname suffix to match wildcard config
* @return mixed Status_network or null
*/ */
static function setupSite($servername, $pathname, $wildcard) static function getFromHostname($servername, $wildcard)
{ {
global $config;
$sn = null; $sn = null;
// XXX I18N, probably not crucial for hostnames
// XXX This probably needs a tune up
if (0 == strncasecmp(strrev($wildcard), strrev($servername), strlen($wildcard))) { if (0 == strncasecmp(strrev($wildcard), strrev($servername), strlen($wildcard))) {
// special case for exact match // special case for exact match
if (0 == strcasecmp($servername, $wildcard)) { if (0 == strcasecmp($servername, $wildcard)) {
@ -182,6 +205,23 @@ class Status_network extends Safe_DataObject
} }
} }
} }
return $sn;
}
/**
* @param string $servername hostname
* @param string $pathname URL base path
* @param string $wildcard hostname suffix to match wildcard config
*/
static function setupSite($servername, $pathname, $wildcard)
{
global $config;
$sn = null;
// XXX I18N, probably not crucial for hostnames
// XXX This probably needs a tune up
$sn = self::getFromHostname($servername, $wildcard);
if (!empty($sn)) { if (!empty($sn)) {

View File

@ -88,8 +88,8 @@ class Subscription extends Memcached_DataObject
self::blow('user:notices_with_friends:%d', $subscriber->id); self::blow('user:notices_with_friends:%d', $subscriber->id);
$subscriber->blowSubscriptionsCount(); $subscriber->blowSubscriptionCount();
$other->blowSubscribersCount(); $other->blowSubscriberCount();
$otherUser = User::staticGet('id', $other->id); $otherUser = User::staticGet('id', $other->id);
@ -213,8 +213,8 @@ class Subscription extends Memcached_DataObject
self::blow('user:notices_with_friends:%d', $subscriber->id); self::blow('user:notices_with_friends:%d', $subscriber->id);
$subscriber->blowSubscriptionsCount(); $subscriber->blowSubscriptionCount();
$other->blowSubscribersCount(); $other->blowSubscriberCount();
Event::handle('EndUnsubscribe', array($subscriber, $other)); Event::handle('EndUnsubscribe', array($subscriber, $other));
} }

View File

@ -524,7 +524,7 @@ class User extends Memcached_DataObject
if ($this->id == $other->id) { if ($this->id == $other->id) {
common_log(LOG_WARNING, common_log(LOG_WARNING,
sprintf( sprintf(
"Profile ID %d (%s) tried to block his or herself.", "Profile ID %d (%s) tried to block themself.",
$this->id, $this->id,
$this->nickname $this->nickname
) )

View File

@ -154,6 +154,21 @@ class User_group extends Memcached_DataObject
return $members; return $members;
} }
function getMemberCount()
{
// XXX: WORM cache this
$members = $this->getMembers();
$member_count = 0;
/** $member->count() doesn't work. */
while ($members->fetch()) {
$member_count++;
}
return $member_count;
}
function getAdmins($offset=0, $limit=null) function getAdmins($offset=0, $limit=null)
{ {
$qry = $qry =

View File

@ -45,7 +45,7 @@ $config['site']['path'] = 'statusnet';
// lighttpd, nginx), you can enable X-Sendfile support for better // lighttpd, nginx), you can enable X-Sendfile support for better
// performance. Presently, only attachment serving when the site is // performance. Presently, only attachment serving when the site is
// in private mode will use X-Sendfile. // in private mode will use X-Sendfile.
// $config['site']['X-Sendfile'] = false; // $config['site']['use_x_sendfile'] = false;
// You may also need to enable X-Sendfile support for your web server and // You may also need to enable X-Sendfile support for your web server and
// allow it to access files outside of the web root. For Apache with // allow it to access files outside of the web root. For Apache with
// mod_xsendfile, you can add these to your .htaccess or server config: // mod_xsendfile, you can add these to your .htaccess or server config:

View File

@ -81,3 +81,42 @@ ALTER TABLE profile ADD COLUMN lon decimal(10,7) /*comment 'longitude'*/;
ALTER TABLE profile ADD COLUMN location_id integer /* comment 'location id if possible'*/; ALTER TABLE profile ADD COLUMN location_id integer /* comment 'location id if possible'*/;
ALTER TABLE profile ADD COLUMN location_ns integer /* comment 'namespace for location'*/; ALTER TABLE profile ADD COLUMN location_ns integer /* comment 'namespace for location'*/;
ALTER TABLE consumer add COLUMN consumer_secret varchar(255) not null ; /*comment 'secret value'*/
ALTER TABLE token ADD COLUMN verifier varchar(255); /* comment 'verifier string for OAuth 1.0a',*/
ALTER TABLE token ADD COLUMN verified_callback varchar(255); /* comment 'verified callback URL for OAuth 1.0a',*/
create table queue_item_new (
id serial /* comment 'unique identifier'*/,
frame bytea not null /* comment 'data: object reference or opaque string'*/,
transport varchar(8) not null /*comment 'queue for what? "email", "jabber", "sms", "irc", ...'*/,
created timestamp not null default CURRENT_TIMESTAMP /*comment 'date this record was created'*/,
claimed timestamp /*comment 'date this item was claimed'*/,
PRIMARY KEY (id)
);
insert into queue_item_new (frame,transport,created,claimed)
select ('0x' || notice_id::text)::bytea,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 confirm_address ALTER column sent set default CURRENT_TIMESTAMP;
create table user_location_prefs (
user_id integer not null /*comment 'user who has the preference'*/ references "user" (id),
share_location int default 1 /* comment 'Whether to share location data'*/,
created timestamp not null /*comment 'date this record was created'*/,
modified timestamp /* comment 'date this record was modified'*/,
primary key (user_id)
);
create table inbox (
user_id integer not null /* comment 'user receiving the notice' */ references "user" (id),
notice_ids bytea /* comment 'packed list of notice ids' */,
primary key (user_id)
);

View File

@ -9,6 +9,7 @@ VALUES
('bti','bti','http://gregkh.github.com/bti/', now()), ('bti','bti','http://gregkh.github.com/bti/', now()),
('choqok', 'Choqok', 'http://choqok.gnufolks.org/', now()), ('choqok', 'Choqok', 'http://choqok.gnufolks.org/', now()),
('cliqset', 'Cliqset', 'http://www.cliqset.com/', now()), ('cliqset', 'Cliqset', 'http://www.cliqset.com/', now()),
('DarterosStatus', 'Darteros Status', 'http://www.darteros.com/doc/Darteros_Status', now()),
('deskbar','Deskbar-Applet','http://www.gnome.org/projects/deskbar-applet/', now()), ('deskbar','Deskbar-Applet','http://www.gnome.org/projects/deskbar-applet/', now()),
('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()), ('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()),
('drupal','Drupal','http://drupal.org/', now()), ('drupal','Drupal','http://drupal.org/', now()),
@ -17,6 +18,7 @@ VALUES
('Facebook','Facebook','http://apps.facebook.com/identica/', now()), ('Facebook','Facebook','http://apps.facebook.com/identica/', now()),
('feed2omb','feed2omb','http://projects.ciarang.com/p/feed2omb/', now()), ('feed2omb','feed2omb','http://projects.ciarang.com/p/feed2omb/', now()),
('get2gnow', 'get2gnow', 'http://uberchicgeekchick.com/?projects=get2gnow', now()), ('get2gnow', 'get2gnow', 'http://uberchicgeekchick.com/?projects=get2gnow', now()),
('gNewBook', 'gNewBook', 'http://www.gnewbook.org/', now()),
('gravity', 'Gravity', 'http://mobileways.de/gravity', now()), ('gravity', 'Gravity', 'http://mobileways.de/gravity', now()),
('Gwibber','Gwibber','http://launchpad.net/gwibber', now()), ('Gwibber','Gwibber','http://launchpad.net/gwibber', now()),
('HelloTxt','HelloTxt','http://hellotxt.com/', now()), ('HelloTxt','HelloTxt','http://hellotxt.com/', now()),
@ -49,6 +51,7 @@ VALUES
('smob','SMOB','http://smob.sioc-project.org/', now()), ('smob','SMOB','http://smob.sioc-project.org/', now()),
('socialoomphBfD4pMqz31', 'SocialOomph', 'http://www.socialoomph.com/', now()), ('socialoomphBfD4pMqz31', 'SocialOomph', 'http://www.socialoomph.com/', now()),
('spaz','Spaz','http://funkatron.com/spaz', now()), ('spaz','Spaz','http://funkatron.com/spaz', now()),
('StatusNet Desktop', 'StatusNet Desktop', 'http://status.net/desktop', now()),
('tarpipe','tarpipe','http://tarpipe.com/', now()), ('tarpipe','tarpipe','http://tarpipe.com/', now()),
('tjunar','Tjunar','http://nederflash.nl/boek/titels/tjunar-air', now()), ('tjunar','Tjunar','http://nederflash.nl/boek/titels/tjunar-air', now()),
('tr.im','tr.im','http://tr.im/', now()), ('tr.im','tr.im','http://tr.im/', now()),

View File

@ -8,6 +8,10 @@ create table profile (
homepage varchar(255) /* comment 'identifying URL' */, homepage varchar(255) /* comment 'identifying URL' */,
bio varchar(140) /* comment 'descriptive biography' */, bio varchar(140) /* comment 'descriptive biography' */,
location varchar(255) /* comment 'physical location' */, location varchar(255) /* comment 'physical location' */,
lat decimal(10,7) /* comment 'latitude'*/ ,
lon decimal(10,7) /* comment 'longitude'*/ ,
location_id integer /* comment 'location id if possible'*/ ,
location_ns integer /* comment 'namespace for location'*/ ,
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */, created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
modified timestamp /* comment 'date this record was modified' */, modified timestamp /* comment 'date this record was modified' */,
@ -132,6 +136,7 @@ create table notice (
is_local integer default 0 /* comment 'notice was generated by a user' */, is_local integer default 0 /* comment 'notice was generated by a user' */,
source varchar(32) /* comment 'source of comment, like "web", "im", or "clientname"' */, source varchar(32) /* comment 'source of comment, like "web", "im", or "clientname"' */,
conversation integer /*id of root notice in this conversation' */ references notice (id), conversation integer /*id of root notice in this conversation' */ references notice (id),
location varchar(255) /* comment 'physical location' */,
lat decimal(10,7) /* comment 'latitude'*/ , lat decimal(10,7) /* comment 'latitude'*/ ,
lon decimal(10,7) /* comment 'longitude'*/ , lon decimal(10,7) /* comment 'longitude'*/ ,
location_id integer /* comment 'location id if possible'*/ , location_id integer /* comment 'location id if possible'*/ ,
@ -182,6 +187,7 @@ create index fave_modified_idx on fave using btree(modified);
create table consumer ( create table consumer (
consumer_key varchar(255) primary key /* comment 'unique identifier, root URL' */, consumer_key varchar(255) primary key /* comment 'unique identifier, root URL' */,
consumer_secret varchar(255) not null /* comment 'secret value', */,
seed char(32) not null /* comment 'seed for new tokens by this consumer' */, seed char(32) not null /* comment 'seed for new tokens by this consumer' */,
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */, created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
@ -195,6 +201,9 @@ create table token (
type integer not null default 0 /* comment 'request or access' */, type integer not null default 0 /* comment 'request or access' */,
state integer default 0 /* comment 'for requests 0 = initial, 1 = authorized, 2 = used' */, state integer default 0 /* comment 'for requests 0 = initial, 1 = authorized, 2 = used' */,
verifier varchar(255) /*comment 'verifier string for OAuth 1.0a'*/,
verified_callback varchar(255) /*comment 'verified callback URL for OAuth 1.0a'*/,
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */, created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
modified timestamp /* comment 'date this record was modified' */, modified timestamp /* comment 'date this record was modified' */,
@ -213,17 +222,33 @@ create table nonce (
primary key (consumer_key, ts, nonce) primary key (consumer_key, ts, nonce)
); );
/* One-to-many relationship of user to openid_url */ create sequence oauth_application_seq;
create table oauth_application (
create table user_openid ( id bigint default nextval('oauth_application_seq') primary key /* comment 'unique identifier' */,
canonical varchar(255) primary key /* comment 'Canonical true URL' */, owner integer not null /* comment 'owner of the application' */ references profile (id),
display varchar(255) not null unique /* comment 'URL for viewing, may be different from canonical' */, consumer_key varchar(255) not null /* comment 'application consumer key' */ references consumer (consumer_key),
user_id integer not null /* comment 'user owning this URL' */ references "user" (id) , name varchar(255) unique 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" integer default 0 /* comment 'type of app, 1 = browser, 2 = desktop' */,
access_type integer default 0 /* comment 'default access type, bit 1 = read, bit 2 = write' */,
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */, created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */,
modified timestamp /* comment 'date this record was modified' */ modified timestamp /* comment 'date this record was modified' */
); );
create index user_openid_user_id_idx on user_openid using btree(user_id);
create table oauth_application_user (
profile_id integer not null /* 'user of the application' */ references profile (id),
application_id integer not null /* 'id of the application' */ references oauth_application (id),
access_type integer default 0 /* 'access type, bit 1 = read, bit 2 = write' */,
token varchar(255) /* 'request or access token' */,
created timestamp not null default CURRENT_TIMESTAMP /* 'date this record was created' */,
modified timestamp /* 'date this record was modified' */,
primary key (profile_id, application_id)
);
/* These are used by JanRain OpenID library */ /* These are used by JanRain OpenID library */
@ -251,7 +276,7 @@ create table confirm_address (
address_extra varchar(255) not null default '' /* comment 'carrier ID, for SMS' */, address_extra varchar(255) not null default '' /* comment 'carrier ID, for SMS' */,
address_type varchar(8) not null /* comment 'address type ("email", "jabber", "sms")' */, address_type varchar(8) not null /* comment 'address type ("email", "jabber", "sms")' */,
claimed timestamp /* comment 'date this was claimed for queueing' */, claimed timestamp /* comment 'date this was claimed for queueing' */,
sent timestamp /* comment 'date this was sent for queueing' */, sent timestamp default CURRENT_TIMESTAMP /* comment 'date this was sent for queueing' */,
modified timestamp /* comment 'date this record was modified' */ modified timestamp /* comment 'date this record was modified' */
); );
@ -262,14 +287,12 @@ create table remember_me (
); );
create table queue_item ( create table queue_item (
id serial /* comment 'unique identifier'*/,
notice_id integer not null /* comment 'notice queued' */ references notice (id) , frame bytea not null /* comment 'data: object reference or opaque string'*/,
transport varchar(8) not null /* comment 'queue for what? "email", "jabber", "sms", "irc", ...' */, transport varchar(8) not null /*comment 'queue for what? "email", "jabber", "sms", "irc", ...'*/,
created timestamp not null default CURRENT_TIMESTAMP /* comment 'date this record was created' */, created timestamp not null default CURRENT_TIMESTAMP /*comment 'date this record was created'*/,
claimed timestamp /* comment 'date this item was claimed' */, claimed timestamp /*comment 'date this item was claimed'*/,
PRIMARY KEY (id)
primary key (notice_id, transport)
); );
create index queue_item_created_idx on queue_item using btree(created); create index queue_item_created_idx on queue_item using btree(created);
@ -589,3 +612,39 @@ create table login_token (
primary key (user_id) primary key (user_id)
); );
create table user_location_prefs (
user_id integer not null /* comment 'user who has the preference' */ references "user" (id),
share_location integer default 1 /* comment 'Whether to share location data' */,
created timestamp not null DEFAULT CURRENT_TIMESTAMP /* comment 'date this record was created' */,
modified timestamp /* comment 'date this record was modified' */,
primary key (user_id)
);
create table inbox (
user_id integer not null /* comment 'user receiving the notice' */ references "user" (id),
notice_ids bytea /* comment 'packed list of notice ids' */,
primary key (user_id)
);
create sequence conversation_seq;
create table conversation (
id bigint default nextval('conversation_seq') primary key /* comment 'unique identifier' */,
uri varchar(225) unique /* comment 'URI of the conversation' */,
created timestamp not null DEFAULT CURRENT_TIMESTAMP /* comment 'date this record was created' */,
modified timestamp /* comment 'date this record was modified' */
);
create table local_group (
group_id integer primary key /* comment 'group represented' */ references user_group (id),
nickname varchar(64) unique /* comment 'group represented' */,
created timestamp not null DEFAULT CURRENT_TIMESTAMP /* comment 'date this record was created' */,
modified timestamp /* comment 'date this record was modified' */
);

View File

@ -20,7 +20,7 @@
/** /**
* The library version string * The library version string
*/ */
define('Auth_OpenID_VERSION', '2.1.3'); define('Auth_OpenID_VERSION', '2.2.2');
/** /**
* Require the fetcher code. * Require the fetcher code.
@ -102,9 +102,7 @@ define('Auth_OpenID_digits',
define('Auth_OpenID_punct', define('Auth_OpenID_punct',
"!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"); "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~");
if (Auth_OpenID_getMathLib() === null) { Auth_OpenID_include_init();
Auth_OpenID_setNoMathSupport();
}
/** /**
* The OpenID utility function class. * The OpenID utility function class.
@ -120,7 +118,7 @@ class Auth_OpenID {
* *
* @access private * @access private
*/ */
function isFailure($thing) static function isFailure($thing)
{ {
return is_a($thing, 'Auth_OpenID_FailureResponse'); return is_a($thing, 'Auth_OpenID_FailureResponse');
} }
@ -139,9 +137,12 @@ class Auth_OpenID {
* Returns an empty array if neither GET nor POST was used, or if * Returns an empty array if neither GET nor POST was used, or if
* POST was used but php://input cannot be opened. * POST was used but php://input cannot be opened.
* *
* See background:
* http://lists.openidenabled.com/pipermail/dev/2007-March/000395.html
*
* @access private * @access private
*/ */
function getQuery($query_str=null) static function getQuery($query_str=null)
{ {
$data = array(); $data = array();
@ -177,7 +178,7 @@ class Auth_OpenID {
return $data; return $data;
} }
function params_from_string($str) static function params_from_string($str)
{ {
$chunks = explode("&", $str); $chunks = explode("&", $str);
@ -190,7 +191,7 @@ class Auth_OpenID {
} }
list($k, $v) = $parts; list($k, $v) = $parts;
$data[$k] = urldecode($v); $data[urldecode($k)] = urldecode($v);
} }
return $data; return $data;
@ -203,7 +204,7 @@ class Auth_OpenID {
* *
* @access private * @access private
*/ */
function ensureDir($dir_name) static function ensureDir($dir_name)
{ {
if (is_dir($dir_name) || @mkdir($dir_name)) { if (is_dir($dir_name) || @mkdir($dir_name)) {
return true; return true;
@ -225,7 +226,7 @@ class Auth_OpenID {
* *
* @access private * @access private
*/ */
function addPrefix($values, $prefix) static function addPrefix($values, $prefix)
{ {
$new_values = array(); $new_values = array();
foreach ($values as $s) { foreach ($values as $s) {
@ -241,7 +242,7 @@ class Auth_OpenID {
* *
* @access private * @access private
*/ */
function arrayGet($arr, $key, $fallback = null) static function arrayGet($arr, $key, $fallback = null)
{ {
if (is_array($arr)) { if (is_array($arr)) {
if (array_key_exists($key, $arr)) { if (array_key_exists($key, $arr)) {
@ -261,7 +262,7 @@ class Auth_OpenID {
/** /**
* Replacement for PHP's broken parse_str. * Replacement for PHP's broken parse_str.
*/ */
function parse_str($query) static function parse_str($query)
{ {
if ($query === null) { if ($query === null) {
return null; return null;
@ -278,7 +279,7 @@ class Auth_OpenID {
} }
list($key, $value) = $pair; list($key, $value) = $pair;
$new_parts[$key] = urldecode($value); $new_parts[urldecode($key)] = urldecode($value);
} }
return $new_parts; return $new_parts;
@ -295,7 +296,7 @@ class Auth_OpenID {
* pairs from $data into a URL query string * pairs from $data into a URL query string
* (e.g. "username=bob&id=56"). * (e.g. "username=bob&id=56").
*/ */
function httpBuildQuery($data) static function httpBuildQuery($data)
{ {
$pairs = array(); $pairs = array();
foreach ($data as $key => $value) { foreach ($data as $key => $value) {
@ -323,7 +324,7 @@ class Auth_OpenID {
* @return string $url The original URL with the new parameters added. * @return string $url The original URL with the new parameters added.
* *
*/ */
function appendArgs($url, $args) static function appendArgs($url, $args)
{ {
if (count($args) == 0) { if (count($args) == 0) {
return $url; return $url;
@ -367,7 +368,7 @@ class Auth_OpenID {
* @return string $url The URL resulting from assembling the * @return string $url The URL resulting from assembling the
* specified components. * specified components.
*/ */
function urlunparse($scheme, $host, $port = null, $path = '/', static function urlunparse($scheme, $host, $port = null, $path = '/',
$query = '', $fragment = '') $query = '', $fragment = '')
{ {
@ -412,7 +413,7 @@ class Auth_OpenID {
* @return mixed $new_url The URL after normalization, or null if * @return mixed $new_url The URL after normalization, or null if
* $url was malformed. * $url was malformed.
*/ */
function normalizeUrl($url) static function normalizeUrl($url)
{ {
@$parsed = parse_url($url); @$parsed = parse_url($url);
@ -443,7 +444,7 @@ class Auth_OpenID {
* *
* @access private * @access private
*/ */
function intval($value) static function intval($value)
{ {
$re = "/^\\d+$/"; $re = "/^\\d+$/";
@ -461,7 +462,7 @@ class Auth_OpenID {
* @param string $str The string of bytes to count. * @param string $str The string of bytes to count.
* @return int The number of bytes in $str. * @return int The number of bytes in $str.
*/ */
function bytes($str) static function bytes($str)
{ {
return strlen(bin2hex($str)) / 2; return strlen(bin2hex($str)) / 2;
} }
@ -470,7 +471,7 @@ class Auth_OpenID {
* Get the bytes in a string independently of multibyte support * Get the bytes in a string independently of multibyte support
* conditions. * conditions.
*/ */
function toBytes($str) static function toBytes($str)
{ {
$hex = bin2hex($str); $hex = bin2hex($str);
@ -486,7 +487,7 @@ class Auth_OpenID {
return $b; return $b;
} }
function urldefrag($url) static function urldefrag($url)
{ {
$parts = explode("#", $url, 2); $parts = explode("#", $url, 2);
@ -497,7 +498,7 @@ class Auth_OpenID {
} }
} }
function filter($callback, &$sequence) static function filter($callback, &$sequence)
{ {
$result = array(); $result = array();
@ -510,7 +511,7 @@ class Auth_OpenID {
return $result; return $result;
} }
function update(&$dest, &$src) static function update(&$dest, &$src)
{ {
foreach ($src as $k => $v) { foreach ($src as $k => $v) {
$dest[$k] = $v; $dest[$k] = $v;
@ -524,14 +525,14 @@ class Auth_OpenID {
* *
* @param string $format_string The sprintf format for the message * @param string $format_string The sprintf format for the message
*/ */
function log($format_string) static function log($format_string)
{ {
$args = func_get_args(); $args = func_get_args();
$message = call_user_func_array('sprintf', $args); $message = call_user_func_array('sprintf', $args);
error_log($message); error_log($message);
} }
function autoSubmitHTML($form, $title="OpenId transaction in progress") static function autoSubmitHTML($form, $title="OpenId transaction in progress")
{ {
return("<html>". return("<html>".
"<head><title>". "<head><title>".
@ -549,4 +550,14 @@ class Auth_OpenID {
"</html>"); "</html>");
} }
} }
?>
/*
* Function to run when this file is included.
* Abstracted to a function to make life easier
* for some PHP optimizers.
*/
function Auth_OpenID_include_init() {
if (Auth_OpenID_getMathLib() === null) {
Auth_OpenID_setNoMathSupport();
}
}

View File

@ -38,7 +38,7 @@ class Auth_OpenID_AX {
* @return bool true if $thing is an Auth_OpenID_AX_Error; false * @return bool true if $thing is an Auth_OpenID_AX_Error; false
* if not. * if not.
*/ */
function isError($thing) static function isError($thing)
{ {
return is_a($thing, 'Auth_OpenID_AX_Error'); return is_a($thing, 'Auth_OpenID_AX_Error');
} }
@ -191,7 +191,7 @@ class Auth_OpenID_AX_AttrInfo {
* Construct an attribute information object. For parameter * Construct an attribute information object. For parameter
* details, see the constructor. * details, see the constructor.
*/ */
function make($type_uri, $count=1, $required=false, static function make($type_uri, $count=1, $required=false,
$alias=null) $alias=null)
{ {
if ($alias !== null) { if ($alias !== null) {
@ -235,7 +235,7 @@ class Auth_OpenID_AX_AttrInfo {
* return null If an alias is present in the list of aliases but * return null If an alias is present in the list of aliases but
* is not present in the namespace map. * is not present in the namespace map.
*/ */
function Auth_OpenID_AX_toTypeURIs(&$namespace_map, $alias_list_s) function Auth_OpenID_AX_toTypeURIs($namespace_map, $alias_list_s)
{ {
$uris = array(); $uris = array();
@ -386,7 +386,7 @@ class Auth_OpenID_AX_FetchRequest extends Auth_OpenID_AX_Message {
* Auth_OpenID_AX_FetchRequest extracted from the request message if * Auth_OpenID_AX_FetchRequest extracted from the request message if
* successful * successful
*/ */
function &fromOpenIDRequest($request) static function fromOpenIDRequest($request)
{ {
$m = $request->message; $m = $request->message;
$obj = new Auth_OpenID_AX_FetchRequest(); $obj = new Auth_OpenID_AX_FetchRequest();
@ -484,7 +484,7 @@ class Auth_OpenID_AX_FetchRequest extends Auth_OpenID_AX_Message {
Auth_OpenID::arrayGet($ax_args, 'required')); Auth_OpenID::arrayGet($ax_args, 'required'));
foreach ($required as $type_uri) { foreach ($required as $type_uri) {
$attrib =& $this->requested_attributes[$type_uri]; $attrib = $this->requested_attributes[$type_uri];
$attrib->required = true; $attrib->required = true;
} }
@ -587,7 +587,7 @@ class Auth_OpenID_AX_KeyValueMessage extends Auth_OpenID_AX_Message {
* *
* @access private * @access private
*/ */
function _getExtensionKVArgs(&$aliases) function _getExtensionKVArgs($aliases)
{ {
if ($aliases === null) { if ($aliases === null) {
$aliases = new Auth_OpenID_NamespaceMap(); $aliases = new Auth_OpenID_NamespaceMap();
@ -652,7 +652,7 @@ class Auth_OpenID_AX_KeyValueMessage extends Auth_OpenID_AX_Message {
foreach ($aliases->iteritems() as $pair) { foreach ($aliases->iteritems() as $pair) {
list($type_uri, $alias) = $pair; list($type_uri, $alias) = $pair;
if (array_key_exists('count.' . $alias, $ax_args)) { if (array_key_exists('count.' . $alias, $ax_args) && ($ax_args['count.' . $alias] !== Auth_OpenID_AX_UNLIMITED_VALUES)) {
$count_key = 'count.' . $alias; $count_key = 'count.' . $alias;
$count_s = $ax_args[$count_key]; $count_s = $ax_args[$count_key];
@ -888,7 +888,7 @@ class Auth_OpenID_AX_FetchResponse extends Auth_OpenID_AX_KeyValueMessage {
$ax_args['update_url'] = $update_url; $ax_args['update_url'] = $update_url;
} }
Auth_OpenID::update(&$ax_args, $kv_args); Auth_OpenID::update($ax_args, $kv_args);
return $ax_args; return $ax_args;
} }
@ -922,7 +922,7 @@ class Auth_OpenID_AX_FetchResponse extends Auth_OpenID_AX_KeyValueMessage {
* @return $response A FetchResponse containing the data from the * @return $response A FetchResponse containing the data from the
* OpenID message * OpenID message
*/ */
function fromSuccessResponse($success_response, $signed=true) static function fromSuccessResponse($success_response, $signed=true)
{ {
$obj = new Auth_OpenID_AX_FetchResponse(); $obj = new Auth_OpenID_AX_FetchResponse();
if ($signed) { if ($signed) {
@ -960,7 +960,7 @@ class Auth_OpenID_AX_StoreRequest extends Auth_OpenID_AX_KeyValueMessage {
{ {
$ax_args = $this->_newArgs(); $ax_args = $this->_newArgs();
$kv_args = $this->_getExtensionKVArgs($aliases); $kv_args = $this->_getExtensionKVArgs($aliases);
Auth_OpenID::update(&$ax_args, $kv_args); Auth_OpenID::update($ax_args, $kv_args);
return $ax_args; return $ax_args;
} }
} }
@ -980,7 +980,7 @@ class Auth_OpenID_AX_StoreResponse extends Auth_OpenID_AX_Message {
* Returns Auth_OpenID_AX_Error on error or an * Returns Auth_OpenID_AX_Error on error or an
* Auth_OpenID_AX_StoreResponse object on success. * Auth_OpenID_AX_StoreResponse object on success.
*/ */
function &make($succeeded=true, $error_message=null) function make($succeeded=true, $error_message=null)
{ {
if (($succeeded) && ($error_message !== null)) { if (($succeeded) && ($error_message !== null)) {
return new Auth_OpenID_AX_Error('An error message may only be '. return new Auth_OpenID_AX_Error('An error message may only be '.
@ -1020,4 +1020,3 @@ class Auth_OpenID_AX_StoreResponse extends Auth_OpenID_AX_Message {
} }
} }
?>

View File

@ -94,7 +94,7 @@ class Auth_OpenID_Association {
* @return association An {@link Auth_OpenID_Association} * @return association An {@link Auth_OpenID_Association}
* instance. * instance.
*/ */
function fromExpiresIn($expires_in, $handle, $secret, $assoc_type) static function fromExpiresIn($expires_in, $handle, $secret, $assoc_type)
{ {
$issued = time(); $issued = time();
$lifetime = $expires_in; $lifetime = $expires_in;
@ -132,7 +132,7 @@ class Auth_OpenID_Association {
$handle, $secret, $issued, $lifetime, $assoc_type) $handle, $secret, $issued, $lifetime, $assoc_type)
{ {
if (!in_array($assoc_type, if (!in_array($assoc_type,
Auth_OpenID_getSupportedAssociationTypes())) { Auth_OpenID_getSupportedAssociationTypes(), true)) {
$fmt = 'Unsupported association type (%s)'; $fmt = 'Unsupported association type (%s)';
trigger_error(sprintf($fmt, $assoc_type), E_USER_ERROR); trigger_error(sprintf($fmt, $assoc_type), E_USER_ERROR);
} }
@ -206,7 +206,7 @@ class Auth_OpenID_Association {
* @param string $assoc_s Association as serialized by serialize() * @param string $assoc_s Association as serialized by serialize()
* @return Auth_OpenID_Association $result instance of this class * @return Auth_OpenID_Association $result instance of this class
*/ */
function deserialize($class_name, $assoc_s) static function deserialize($class_name, $assoc_s)
{ {
$pairs = Auth_OpenID_KVForm::toArray($assoc_s, $strict = true); $pairs = Auth_OpenID_KVForm::toArray($assoc_s, $strict = true);
$keys = array(); $keys = array();
@ -327,7 +327,7 @@ class Auth_OpenID_Association {
* *
* @access private * @access private
*/ */
function _makePairs(&$message) function _makePairs($message)
{ {
$signed = $message->getArg(Auth_OpenID_OPENID_NS, 'signed'); $signed = $message->getArg(Auth_OpenID_OPENID_NS, 'signed');
if (!$signed || Auth_OpenID::isFailure($signed)) { if (!$signed || Auth_OpenID::isFailure($signed)) {
@ -352,7 +352,7 @@ class Auth_OpenID_Association {
* *
* @access private * @access private
*/ */
function getMessageSignature(&$message) function getMessageSignature($message)
{ {
$pairs = $this->_makePairs($message); $pairs = $this->_makePairs($message);
return base64_encode($this->sign($pairs)); return base64_encode($this->sign($pairs));
@ -364,7 +364,7 @@ class Auth_OpenID_Association {
* *
* @access private * @access private
*/ */
function checkMessageSignature(&$message) function checkMessageSignature($message)
{ {
$sig = $message->getArg(Auth_OpenID_OPENID_NS, $sig = $message->getArg(Auth_OpenID_OPENID_NS,
'sig'); 'sig');
@ -374,7 +374,42 @@ class Auth_OpenID_Association {
} }
$calculated_sig = $this->getMessageSignature($message); $calculated_sig = $this->getMessageSignature($message);
return $calculated_sig == $sig;
return $this->constantTimeCompare($calculated_sig, $sig);
}
/**
* String comparison function which will complete in a constant time
* for strings of any given matching length, to help prevent an attacker
* from distinguishing how much of a signature token they have guessed
* correctly.
*
* For this usage, it's assumed that the length of the string is known,
* so we may safely short-circuit on mismatched lengths which will be known
* to be invalid by the attacker.
*
* http://lists.openid.net/pipermail/openid-security/2010-July/001156.html
* http://rdist.root.org/2010/01/07/timing-independent-array-comparison/
*/
private function constantTimeCompare($a, $b)
{
$len = strlen($a);
if (strlen($b) !== $len) {
// Short-circuit on length mismatch; attackers will already know
// the correct target length so this is safe.
return false;
}
if ($len == 0) {
// 0-length valid input shouldn't really happen. :)
return true;
}
$result = 0;
for ($i = 0; $i < strlen($a); $i++) {
// We use scary bitwise operations to avoid logical short-circuits
// in lower-level code.
$result |= ord($a{$i}) ^ ord($b{$i});
}
return ($result == 0);
} }
} }
@ -469,18 +504,16 @@ function Auth_OpenID_getOnlyEncryptedOrder()
return $result; return $result;
} }
function &Auth_OpenID_getDefaultNegotiator() function Auth_OpenID_getDefaultNegotiator()
{ {
$x = new Auth_OpenID_SessionNegotiator( return new Auth_OpenID_SessionNegotiator(
Auth_OpenID_getDefaultAssociationOrder()); Auth_OpenID_getDefaultAssociationOrder());
return $x;
} }
function &Auth_OpenID_getEncryptedNegotiator() function Auth_OpenID_getEncryptedNegotiator()
{ {
$x = new Auth_OpenID_SessionNegotiator( return new Auth_OpenID_SessionNegotiator(
Auth_OpenID_getOnlyEncryptedOrder()); Auth_OpenID_getOnlyEncryptedOrder());
return $x;
} }
/** /**
@ -610,4 +643,3 @@ class Auth_OpenID_SessionNegotiator {
} }
} }
?>

View File

@ -351,8 +351,7 @@ function Auth_OpenID_math_extensions()
'class' => 'Auth_OpenID_GmpMathWrapper'); 'class' => 'Auth_OpenID_GmpMathWrapper');
} }
$result[] = array( $result[] = array('modules' => array('bcmath', 'php_bcmath'),
'modules' => array('bcmath', 'php_bcmath'),
'extension' => 'bcmath', 'extension' => 'bcmath',
'class' => 'Auth_OpenID_BcMathWrapper'); 'class' => 'Auth_OpenID_BcMathWrapper');
@ -366,27 +365,9 @@ function Auth_OpenID_detectMathLibrary($exts)
{ {
$loaded = false; $loaded = false;
$hasDl = function_exists('dl');
foreach ($exts as $extension) { foreach ($exts as $extension) {
// See if the extension specified is already loaded. if (extension_loaded($extension['extension'])) {
if ($extension['extension'] &&
extension_loaded($extension['extension'])) {
$loaded = true;
}
// Try to load dynamic modules.
if (!$loaded) {
foreach ($extension['modules'] as $module) {
if (@dl($module . "." . PHP_SHLIB_SUFFIX)) {
$loaded = true;
break;
}
}
}
// If the load succeeded, supply an instance of
// Auth_OpenID_MathWrapper which wraps the specified
// module's functionality.
if ($loaded) {
return $extension; return $extension;
} }
} }
@ -405,7 +386,7 @@ function Auth_OpenID_detectMathLibrary($exts)
* instance of a wrapper for that extension module. If no extension * instance of a wrapper for that extension module. If no extension
* module is found, an instance of {@link Auth_OpenID_MathWrapper} is * module is found, an instance of {@link Auth_OpenID_MathWrapper} is
* returned, which wraps the native PHP integer implementation. The * returned, which wraps the native PHP integer implementation. The
* proper calling convention for this method is $lib =& * proper calling convention for this method is $lib =
* Auth_OpenID_getMathLib(). * Auth_OpenID_getMathLib().
* *
* This function checks for the existence of specific long number * This function checks for the existence of specific long number
@ -416,7 +397,7 @@ function Auth_OpenID_detectMathLibrary($exts)
* *
* @package OpenID * @package OpenID
*/ */
function &Auth_OpenID_getMathLib() function Auth_OpenID_getMathLib()
{ {
// The instance of Auth_OpenID_MathWrapper that we choose to // The instance of Auth_OpenID_MathWrapper that we choose to
// supply will be stored here, so that subseqent calls to this // supply will be stored here, so that subseqent calls to this
@ -468,4 +449,4 @@ function Auth_OpenID_noMathSupport()
return defined('Auth_OpenID_NO_MATH_SUPPORT'); return defined('Auth_OpenID_NO_MATH_SUPPORT');
} }
?>

View File

@ -258,19 +258,19 @@ class Auth_OpenID_Consumer {
* when creating the internal consumer object. This is used for * when creating the internal consumer object. This is used for
* testing. * testing.
*/ */
function Auth_OpenID_Consumer(&$store, $session = null, function Auth_OpenID_Consumer($store, $session = null,
$consumer_cls = null) $consumer_cls = null)
{ {
if ($session === null) { if ($session === null) {
$session = new Auth_Yadis_PHPSession(); $session = new Auth_Yadis_PHPSession();
} }
$this->session =& $session; $this->session = $session;
if ($consumer_cls !== null) { if ($consumer_cls !== null) {
$this->consumer =& new $consumer_cls($store); $this->consumer = new $consumer_cls($store);
} else { } else {
$this->consumer =& new Auth_OpenID_GenericConsumer($store); $this->consumer = new Auth_OpenID_GenericConsumer($store);
} }
$this->_token_key = $this->session_key_prefix . $this->_token_suffix; $this->_token_key = $this->session_key_prefix . $this->_token_suffix;
@ -281,7 +281,7 @@ class Auth_OpenID_Consumer {
* *
* @access private * @access private
*/ */
function getDiscoveryObject(&$session, $openid_url, function getDiscoveryObject($session, $openid_url,
$session_key_prefix) $session_key_prefix)
{ {
return new Auth_Yadis_Discovery($session, $openid_url, return new Auth_Yadis_Discovery($session, $openid_url,
@ -339,7 +339,7 @@ class Auth_OpenID_Consumer {
$this->consumer->fetcher); $this->consumer->fetcher);
// Reset the 'stale' attribute of the manager. // Reset the 'stale' attribute of the manager.
$m =& $disco->getManager(); $m = $disco->getManager();
if ($m) { if ($m) {
$m->stale = false; $m->stale = false;
$disco->session->set($disco->session_key, $disco->session->set($disco->session_key,
@ -370,7 +370,7 @@ class Auth_OpenID_Consumer {
* @return Auth_OpenID_AuthRequest $auth_request An OpenID * @return Auth_OpenID_AuthRequest $auth_request An OpenID
* authentication request object. * authentication request object.
*/ */
function &beginWithoutDiscovery($endpoint, $anonymous=false) function beginWithoutDiscovery($endpoint, $anonymous=false)
{ {
$loader = new Auth_OpenID_ServiceEndpointLoader(); $loader = new Auth_OpenID_ServiceEndpointLoader();
$auth_req = $this->consumer->begin($endpoint); $auth_req = $this->consumer->begin($endpoint);
@ -467,7 +467,7 @@ class Auth_OpenID_DiffieHellmanSHA1ConsumerSession {
function getRequest() function getRequest()
{ {
$math =& Auth_OpenID_getMathLib(); $math = Auth_OpenID_getMathLib();
$cpub = $math->longToBase64($this->dh->public); $cpub = $math->longToBase64($this->dh->public);
@ -496,7 +496,7 @@ class Auth_OpenID_DiffieHellmanSHA1ConsumerSession {
return null; return null;
} }
$math =& Auth_OpenID_getMathLib(); $math = Auth_OpenID_getMathLib();
$spub = $math->base64ToLong($response->getArg(Auth_OpenID_OPENID_NS, $spub = $math->base64ToLong($response->getArg(Auth_OpenID_OPENID_NS,
'dh_server_public')); 'dh_server_public'));
@ -611,11 +611,11 @@ class Auth_OpenID_GenericConsumer {
* in the module description. The default value is False, which * in the module description. The default value is False, which
* disables immediate mode. * disables immediate mode.
*/ */
function Auth_OpenID_GenericConsumer(&$store) function Auth_OpenID_GenericConsumer($store)
{ {
$this->store =& $store; $this->store = $store;
$this->negotiator =& Auth_OpenID_getDefaultNegotiator(); $this->negotiator = Auth_OpenID_getDefaultNegotiator();
$this->_use_assocs = ($this->store ? true : false); $this->_use_assocs = (is_null($this->store) ? false : true);
$this->fetcher = Auth_Yadis_Yadis::getHTTPFetcher(); $this->fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
@ -665,14 +665,14 @@ class Auth_OpenID_GenericConsumer {
$method = Auth_OpenID::arrayGet($mode_methods, $mode, $method = Auth_OpenID::arrayGet($mode_methods, $mode,
'_completeInvalid'); '_completeInvalid');
return call_user_func_array(array(&$this, $method), return call_user_func_array(array($this, $method),
array($message, $endpoint, $return_to)); array($message, &$endpoint, $return_to));
} }
/** /**
* @access private * @access private
*/ */
function _completeInvalid($message, &$endpoint, $unused) function _completeInvalid($message, $endpoint, $unused)
{ {
$mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode', $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode',
'<No mode set>'); '<No mode set>');
@ -684,7 +684,7 @@ class Auth_OpenID_GenericConsumer {
/** /**
* @access private * @access private
*/ */
function _complete_cancel($message, &$endpoint, $unused) function _complete_cancel($message, $endpoint, $unused)
{ {
return new Auth_OpenID_CancelResponse($endpoint); return new Auth_OpenID_CancelResponse($endpoint);
} }
@ -692,7 +692,7 @@ class Auth_OpenID_GenericConsumer {
/** /**
* @access private * @access private
*/ */
function _complete_error($message, &$endpoint, $unused) function _complete_error($message, $endpoint, $unused)
{ {
$error = $message->getArg(Auth_OpenID_OPENID_NS, 'error'); $error = $message->getArg(Auth_OpenID_OPENID_NS, 'error');
$contact = $message->getArg(Auth_OpenID_OPENID_NS, 'contact'); $contact = $message->getArg(Auth_OpenID_OPENID_NS, 'contact');
@ -705,7 +705,7 @@ class Auth_OpenID_GenericConsumer {
/** /**
* @access private * @access private
*/ */
function _complete_setup_needed($message, &$endpoint, $unused) function _complete_setup_needed($message, $endpoint, $unused)
{ {
if (!$message->isOpenID2()) { if (!$message->isOpenID2()) {
return $this->_completeInvalid($message, $endpoint); return $this->_completeInvalid($message, $endpoint);
@ -719,7 +719,7 @@ class Auth_OpenID_GenericConsumer {
/** /**
* @access private * @access private
*/ */
function _complete_id_res($message, &$endpoint, $return_to) function _complete_id_res($message, $endpoint, $return_to)
{ {
$user_setup_url = $message->getArg(Auth_OpenID_OPENID1_NS, $user_setup_url = $message->getArg(Auth_OpenID_OPENID1_NS,
'user_setup_url'); 'user_setup_url');
@ -1181,7 +1181,7 @@ class Auth_OpenID_GenericConsumer {
// oidutil.log('Performing discovery on %s' % (claimed_id,)) // oidutil.log('Performing discovery on %s' % (claimed_id,))
list($unused, $services) = call_user_func($this->discoverMethod, list($unused, $services) = call_user_func($this->discoverMethod,
$claimed_id, $claimed_id,
$this->fetcher); &$this->fetcher);
if (!$services) { if (!$services) {
return new Auth_OpenID_FailureResponse(null, return new Auth_OpenID_FailureResponse(null,
@ -1197,7 +1197,7 @@ class Auth_OpenID_GenericConsumer {
* @access private * @access private
*/ */
function _verifyDiscoveryServices($claimed_id, function _verifyDiscoveryServices($claimed_id,
&$services, &$to_match_endpoints) $services, $to_match_endpoints)
{ {
// Search the services resulting from discovery to find one // Search the services resulting from discovery to find one
// that matches the information from the assertion // that matches the information from the assertion
@ -1216,8 +1216,8 @@ class Auth_OpenID_GenericConsumer {
} }
return new Auth_OpenID_FailureResponse(null, return new Auth_OpenID_FailureResponse(null,
sprintf('No matching endpoint found after discovering %s', sprintf('No matching endpoint found after discovering %s: %s',
$claimed_id)); $claimed_id, $result->message));
} }
/** /**
@ -1397,7 +1397,7 @@ class Auth_OpenID_GenericConsumer {
* *
* @access private * @access private
*/ */
function _httpResponseToMessage($response, $server_url) static function _httpResponseToMessage($response, $server_url)
{ {
// Should this function be named Message.fromHTTPResponse instead? // Should this function be named Message.fromHTTPResponse instead?
$response_message = Auth_OpenID_Message::fromKVForm($response->body); $response_message = Auth_OpenID_Message::fromKVForm($response->body);
@ -1461,7 +1461,7 @@ class Auth_OpenID_GenericConsumer {
* *
* @access private * @access private
*/ */
function _extractSupportedAssociationType(&$server_error, &$endpoint, function _extractSupportedAssociationType($server_error, $endpoint,
$assoc_type) $assoc_type)
{ {
// Any error message whose code is not 'unsupported-type' // Any error message whose code is not 'unsupported-type'
@ -1566,7 +1566,7 @@ class Auth_OpenID_GenericConsumer {
/** /**
* @access private * @access private
*/ */
function _extractAssociation(&$assoc_response, &$assoc_session) function _extractAssociation($assoc_response, $assoc_session)
{ {
// Extract the common fields from the response, raising an // Extract the common fields from the response, raising an
// exception if they are not found // exception if they are not found
@ -1748,10 +1748,10 @@ class Auth_OpenID_AuthRequest {
* class. Instances of this class are created by the library when * class. Instances of this class are created by the library when
* needed. * needed.
*/ */
function Auth_OpenID_AuthRequest(&$endpoint, $assoc) function Auth_OpenID_AuthRequest($endpoint, $assoc)
{ {
$this->assoc = $assoc; $this->assoc = $assoc;
$this->endpoint =& $endpoint; $this->endpoint = $endpoint;
$this->return_to_args = array(); $this->return_to_args = array();
$this->message = new Auth_OpenID_Message( $this->message = new Auth_OpenID_Message(
$endpoint->preferredNamespace()); $endpoint->preferredNamespace());
@ -1764,7 +1764,7 @@ class Auth_OpenID_AuthRequest {
* $extension_request: An object that implements the extension * $extension_request: An object that implements the extension
* request interface for adding arguments to an OpenID message. * request interface for adding arguments to an OpenID message.
*/ */
function addExtension(&$extension_request) function addExtension($extension_request)
{ {
$extension_request->toMessage($this->message); $extension_request->toMessage($this->message);
} }
@ -2089,7 +2089,7 @@ class Auth_OpenID_SuccessResponse extends Auth_OpenID_ConsumerResponse {
foreach ($msg_args as $key => $value) { foreach ($msg_args as $key => $value) {
if (!$this->isSigned($ns_uri, $key)) { if (!$this->isSigned($ns_uri, $key)) {
return null; unset($msg_args[$key]);
} }
} }
@ -2167,7 +2167,7 @@ class Auth_OpenID_ServerErrorContainer {
/** /**
* @access private * @access private
*/ */
function fromMessage($message) static function fromMessage($message)
{ {
$error_text = $message->getArg( $error_text = $message->getArg(
Auth_OpenID_OPENID_NS, 'error', '<no error message supplied>'); Auth_OpenID_OPENID_NS, 'error', '<no error message supplied>');
@ -2227,4 +2227,4 @@ class Auth_OpenID_SetupNeededResponse extends Auth_OpenID_ConsumerResponse {
} }
} }
?>

View File

@ -37,7 +37,7 @@ class Auth_OpenID_CryptUtil {
* @param int $num_bytes The length of the return value * @param int $num_bytes The length of the return value
* @return string $bytes random bytes * @return string $bytes random bytes
*/ */
function getBytes($num_bytes) static function getBytes($num_bytes)
{ {
static $f = null; static $f = null;
$bytes = ''; $bytes = '';
@ -77,7 +77,7 @@ class Auth_OpenID_CryptUtil {
* @return string $result A string of randomly-chosen characters * @return string $result A string of randomly-chosen characters
* from $chrs * from $chrs
*/ */
function randomString($length, $population = null) static function randomString($length, $population = null)
{ {
if ($population === null) { if ($population === null) {
return Auth_OpenID_CryptUtil::getBytes($length); return Auth_OpenID_CryptUtil::getBytes($length);
@ -106,4 +106,3 @@ class Auth_OpenID_CryptUtil {
} }
} }
?>

View File

@ -128,4 +128,3 @@ class Auth_OpenID_DatabaseConnection {
} }
} }
?>

View File

@ -51,9 +51,9 @@ class Auth_OpenID_DiffieHellman {
$private = null, $lib = null) $private = null, $lib = null)
{ {
if ($lib === null) { if ($lib === null) {
$this->lib =& Auth_OpenID_getMathLib(); $this->lib = Auth_OpenID_getMathLib();
} else { } else {
$this->lib =& $lib; $this->lib = $lib;
} }
if ($mod === null) { if ($mod === null) {
@ -110,4 +110,4 @@ class Auth_OpenID_DiffieHellman {
} }
} }
?>

View File

@ -28,8 +28,34 @@ function Auth_OpenID_getOpenIDTypeURIs()
Auth_OpenID_TYPE_2_0, Auth_OpenID_TYPE_2_0,
Auth_OpenID_TYPE_1_2, Auth_OpenID_TYPE_1_2,
Auth_OpenID_TYPE_1_1, Auth_OpenID_TYPE_1_1,
Auth_OpenID_TYPE_1_0, Auth_OpenID_TYPE_1_0);
Auth_OpenID_RP_RETURN_TO_URL_TYPE); }
function Auth_OpenID_getOpenIDConsumerTypeURIs()
{
return array(Auth_OpenID_RP_RETURN_TO_URL_TYPE);
}
/*
* Provides a user-readable interpretation of a type uri.
* Useful for error messages.
*/
function Auth_OpenID_getOpenIDTypeName($type_uri) {
switch ($type_uri) {
case Auth_OpenID_TYPE_2_0_IDP:
return 'OpenID 2.0 IDP';
case Auth_OpenID_TYPE_2_0:
return 'OpenID 2.0';
case Auth_OpenID_TYPE_1_2:
return 'OpenID 1.2';
case Auth_OpenID_TYPE_1_1:
return 'OpenID 1.1';
case Auth_OpenID_TYPE_1_0:
return 'OpenID 1.0';
case Auth_OpenID_RP_RETURN_TO_URL_TYPE:
return 'OpenID relying party';
}
} }
/** /**
@ -124,7 +150,7 @@ class Auth_OpenID_ServiceEndpoint {
return in_array(Auth_OpenID_TYPE_2_0_IDP, $this->type_uris); return in_array(Auth_OpenID_TYPE_2_0_IDP, $this->type_uris);
} }
function fromOPEndpointURL($op_endpoint_url) static function fromOPEndpointURL($op_endpoint_url)
{ {
// Construct an OP-Identifier OpenIDServiceEndpoint object for // Construct an OP-Identifier OpenIDServiceEndpoint object for
// a given OP Endpoint URL // a given OP Endpoint URL
@ -171,15 +197,34 @@ class Auth_OpenID_ServiceEndpoint {
} }
} }
/*
* Parse the given document as XRDS looking for OpenID consumer services.
*
* @return array of Auth_OpenID_ServiceEndpoint or null if the
* document cannot be parsed.
*/
function consumerFromXRDS($uri, $xrds_text)
{
$xrds =& Auth_Yadis_XRDS::parseXRDS($xrds_text);
if ($xrds) {
$yadis_services =
$xrds->services(array('filter_MatchesAnyOpenIDConsumerType'));
return Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services);
}
return null;
}
/* /*
* Parse the given document as XRDS looking for OpenID services. * Parse the given document as XRDS looking for OpenID services.
* *
* @return array of Auth_OpenID_ServiceEndpoint or null if the * @return array of Auth_OpenID_ServiceEndpoint or null if the
* document cannot be parsed. * document cannot be parsed.
*/ */
function fromXRDS($uri, $xrds_text) static function fromXRDS($uri, $xrds_text)
{ {
$xrds =& Auth_Yadis_XRDS::parseXRDS($xrds_text); $xrds = Auth_Yadis_XRDS::parseXRDS($xrds_text);
if ($xrds) { if ($xrds) {
$yadis_services = $yadis_services =
@ -197,7 +242,7 @@ class Auth_OpenID_ServiceEndpoint {
* @return array of Auth_OpenID_ServiceEndpoint or null if * @return array of Auth_OpenID_ServiceEndpoint or null if
* endpoints cannot be created. * endpoints cannot be created.
*/ */
function fromDiscoveryResult($discoveryResult) static function fromDiscoveryResult($discoveryResult)
{ {
if ($discoveryResult->isXRDS()) { if ($discoveryResult->isXRDS()) {
return Auth_OpenID_ServiceEndpoint::fromXRDS( return Auth_OpenID_ServiceEndpoint::fromXRDS(
@ -210,7 +255,7 @@ class Auth_OpenID_ServiceEndpoint {
} }
} }
function fromHTML($uri, $html) static function fromHTML($uri, $html)
{ {
$discovery_types = array( $discovery_types = array(
array(Auth_OpenID_TYPE_2_0, array(Auth_OpenID_TYPE_2_0,
@ -273,7 +318,7 @@ function Auth_OpenID_findOPLocalIdentifier($service, $type_uris)
$service->parser->registerNamespace('xrd', $service->parser->registerNamespace('xrd',
Auth_Yadis_XMLNS_XRD_2_0); Auth_Yadis_XMLNS_XRD_2_0);
$parser =& $service->parser; $parser = $service->parser;
$permitted_tags = array(); $permitted_tags = array();
@ -305,7 +350,7 @@ function Auth_OpenID_findOPLocalIdentifier($service, $type_uris)
return $local_id; return $local_id;
} }
function filter_MatchesAnyOpenIDType(&$service) function filter_MatchesAnyOpenIDType($service)
{ {
$uris = $service->getTypes(); $uris = $service->getTypes();
@ -318,6 +363,19 @@ function filter_MatchesAnyOpenIDType(&$service)
return false; return false;
} }
function filter_MatchesAnyOpenIDConsumerType(&$service)
{
$uris = $service->getTypes();
foreach ($uris as $uri) {
if (in_array($uri, Auth_OpenID_getOpenIDConsumerTypeURIs())) {
return true;
}
}
return false;
}
function Auth_OpenID_bestMatchingService($service, $preferred_types) function Auth_OpenID_bestMatchingService($service, $preferred_types)
{ {
// Return the index of the first matching type, or something // Return the index of the first matching type, or something
@ -415,7 +473,7 @@ function Auth_OpenID_makeOpenIDEndpoints($uri, $yadis_services)
return $s; return $s;
} }
function Auth_OpenID_discoverWithYadis($uri, &$fetcher, function Auth_OpenID_discoverWithYadis($uri, $fetcher,
$endpoint_filter='Auth_OpenID_getOPOrUserServices', $endpoint_filter='Auth_OpenID_getOPOrUserServices',
$discover_function=null) $discover_function=null)
{ {
@ -433,12 +491,12 @@ function Auth_OpenID_discoverWithYadis($uri, &$fetcher,
$openid_services = array(); $openid_services = array();
$response = call_user_func_array($discover_function, $response = call_user_func_array($discover_function,
array($uri, &$fetcher)); array($uri, $fetcher));
$yadis_url = $response->normalized_uri; $yadis_url = $response->normalized_uri;
$yadis_services = array(); $yadis_services = array();
if ($response->isFailure()) { if ($response->isFailure() && !$response->isXRDS()) {
return array($uri, array()); return array($uri, array());
} }
@ -460,18 +518,18 @@ function Auth_OpenID_discoverWithYadis($uri, &$fetcher,
} }
$openid_services = call_user_func_array($endpoint_filter, $openid_services = call_user_func_array($endpoint_filter,
array(&$openid_services)); array($openid_services));
return array($yadis_url, $openid_services); return array($yadis_url, $openid_services);
} }
function Auth_OpenID_discoverURI($uri, &$fetcher) function Auth_OpenID_discoverURI($uri, $fetcher)
{ {
$uri = Auth_OpenID::normalizeUrl($uri); $uri = Auth_OpenID::normalizeUrl($uri);
return Auth_OpenID_discoverWithYadis($uri, $fetcher); return Auth_OpenID_discoverWithYadis($uri, $fetcher);
} }
function Auth_OpenID_discoverWithoutYadis($uri, &$fetcher) function Auth_OpenID_discoverWithoutYadis($uri, $fetcher)
{ {
$http_resp = @$fetcher->get($uri); $http_resp = @$fetcher->get($uri);
@ -490,7 +548,7 @@ function Auth_OpenID_discoverWithoutYadis($uri, &$fetcher)
return array($identity_url, $openid_services); return array($identity_url, $openid_services);
} }
function Auth_OpenID_discoverXRI($iname, &$fetcher) function Auth_OpenID_discoverXRI($iname, $fetcher)
{ {
$resolver = new Auth_Yadis_ProxyResolver($fetcher); $resolver = new Auth_Yadis_ProxyResolver($fetcher);
list($canonicalID, $yadis_services) = list($canonicalID, $yadis_services) =
@ -513,7 +571,7 @@ function Auth_OpenID_discoverXRI($iname, &$fetcher)
return array($iname, $openid_services); return array($iname, $openid_services);
} }
function Auth_OpenID_discover($uri, &$fetcher) function Auth_OpenID_discover($uri, $fetcher)
{ {
// If the fetcher (i.e., PHP) doesn't support SSL, we can't do // If the fetcher (i.e., PHP) doesn't support SSL, we can't do
// discovery on an HTTPS URL. // discovery on an HTTPS URL.
@ -545,4 +603,4 @@ function Auth_OpenID_discover($uri, &$fetcher)
return $result; return $result;
} }
?>

View File

@ -97,4 +97,3 @@ class Auth_OpenID_DumbStore extends Auth_OpenID_OpenIDStore {
} }
} }
?>

View File

@ -39,7 +39,7 @@ class Auth_OpenID_Extension {
* *
* Returns the message with the extension arguments added. * Returns the message with the extension arguments added.
*/ */
function toMessage(&$message) function toMessage($message)
{ {
$implicit = $message->isOpenID1(); $implicit = $message->isOpenID1();
$added = $message->namespaces->addAlias($this->ns_uri, $added = $message->namespaces->addAlias($this->ns_uri,
@ -59,4 +59,3 @@ class Auth_OpenID_Extension {
} }
} }
?>

View File

@ -367,7 +367,7 @@ class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore {
} }
if ( abs($timestamp - time()) > $Auth_OpenID_SKEW ) { if ( abs($timestamp - time()) > $Auth_OpenID_SKEW ) {
return False; return false;
} }
if ($server_url) { if ($server_url) {
@ -519,7 +519,7 @@ class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore {
/** /**
* @access private * @access private
*/ */
function _mkdtemp($dir) static function _mkdtemp($dir)
{ {
foreach (range(0, 4) as $i) { foreach (range(0, 4) as $i) {
$name = $dir . strval(DIRECTORY_SEPARATOR) . strval(getmypid()) . $name = $dir . strval(DIRECTORY_SEPARATOR) . strval(getmypid()) .
@ -615,4 +615,4 @@ class Auth_OpenID_FileStore extends Auth_OpenID_OpenIDStore {
} }
} }
?>

View File

@ -96,4 +96,3 @@ if (function_exists('hash_hmac') &&
define('Auth_OpenID_HMACSHA256_SUPPORTED', false); define('Auth_OpenID_HMACSHA256_SUPPORTED', false);
} }
?>

Some files were not shown because too many files have changed in this diff Show More