var $keys = array(
'site' => array('name', 'server', 'theme', 'path', 'fancy', 'language',
'email', 'broughtby', 'broughtbyurl', 'closed',
- 'inviteonly', 'private'),
+ 'inviteonly', 'private','textlimit'),
'license' => array('url', 'title', 'image'),
'nickname' => array('featured'),
'throttle' => array('enabled', 'count', 'timespan'),
$this->lt->delete();
$this->lt = null;
+ common_real_login(true);
+
if ($this->rememberme) {
common_rememberme($this->user);
}
printf('<p class="error">PHP is linked to a version of the PCRE library ' .
'that does not support Unicode properties. ' .
'If you are running Red Hat Enterprise Linux / ' .
- 'CentOS 5.3 or earlier, see <a href="' .
+ 'CentOS 5.4 or earlier, see <a href="' .
'http://status.net/wiki/Red_Hat_Enterprise_Linux#PCRE_library' .
'">our documentation page</a> on fixing this.</p>');
$pass = false;
$dbRadios .= "<input type=\"radio\" name=\"dbtype\" id=\"dbtype-$type\" value=\"$type\" $checked/> $info[name]<br />\n";
}
}
+
echo<<<E_O_T
</ul>
</dd>
<input id="admin_email" name="admin_email" value="{$post->value('admin_email')}" />
<p class="form_guide">Optional email address for the initial StatusNet user (administrator)</p>
</li>
+ <li>
+ <label for="admin_updates">Subscribe to announcements</label>
+ <input type="checkbox" id="admin_updates" name="admin_updates" value="true" checked="checked" />
+ <p class="form_guide">Release and security feed from <a href="http://update.status.net/">update@status.net</a> (recommended)</p>
+ </li>
</ul>
</fieldset>
<input type="submit" name="submit" class="submit" value="Submit" />
$sitename = $_POST['sitename'];
$fancy = !empty($_POST['fancy']);
- $adminNick = $_POST['admin_nickname'];
+ $adminNick = strtolower($_POST['admin_nickname']);
$adminPass = $_POST['admin_password'];
$adminPass2 = $_POST['admin_password2'];
$adminEmail = $_POST['admin_email'];
+ $adminUpdates = $_POST['admin_updates'];
$server = $_SERVER['HTTP_HOST'];
$path = substr(dirname($_SERVER['PHP_SELF']), 1);
updateStatus("No initial StatusNet user nickname specified.", true);
$fail = true;
}
+ if ($adminNick && !preg_match('/^[0-9a-z]{1,64}$/', $adminNick)) {
+ updateStatus('The user nickname "' . htmlspecialchars($adminNick) .
+ '" is invalid; should be plain letters and numbers no longer than 64 characters.', true);
+ $fail = true;
+ }
+ // @fixme hardcoded list; should use User::allowed_nickname()
+ // if/when it's safe to have loaded the infrastructure here
+ $blacklist = array('main', 'admin', 'twitter', 'settings', 'rsd.xml', 'favorited', 'featured', 'favoritedrss', 'featuredrss', 'rss', 'getfile', 'api', 'groups', 'group', 'peopletag', 'tag', 'user', 'message', 'conversation', 'bookmarklet', 'notice', 'attachment', 'search', 'index.php', 'doc', 'opensearch', 'robots.txt', 'xd_receiver.html', 'facebook');
+ if (in_array($adminNick, $blacklist)) {
+ updateStatus('The user nickname "' . htmlspecialchars($adminNick) .
+ '" is reserved.', true);
+ $fail = true;
+ }
if (empty($adminPass)) {
updateStatus("No initial StatusNet user password specified.", true);
}
// Okay, cross fingers and try to register an initial user
- if (registerInitialUser($adminNick, $adminPass, $adminEmail)) {
+ if (registerInitialUser($adminNick, $adminPass, $adminEmail, $adminUpdates)) {
updateStatus(
"An initial user with the administrator role has been created."
);
return true;
}
-function registerInitialUser($nickname, $password, $email)
+function registerInitialUser($nickname, $password, $email, $adminUpdates)
{
define('STATUSNET', true);
define('LACONICA', true); // compatibility
// Attempt to do a remote subscribe to update@status.net
// Will fail if instance is on a private network.
- if (class_exists('Ostatus_profile')) {
+ if (class_exists('Ostatus_profile') && $adminUpdates) {
try {
$oprofile = Ostatus_profile::ensureProfile('http://update.status.net/');
Subscription::start($user->getProfile(), $oprofile->localProfile());
{
$this->element('dt', array('id' => 'site_statusnet_license'), _('StatusNet software license'));
$this->elementStart('dd', null);
+ // @fixme drop the final spaces in the messages when at good spot
+ // to let translations get updated.
if (common_config('site', 'broughtby')) {
$instr = _('**%%site.name%%** is a microblogging service brought to you by [%%site.broughtby%%](%%site.broughtbyurl%%). ');
} else {
$instr = _('**%%site.name%%** is a microblogging service. ');
}
+ $instr .= ' ';
$instr .= sprintf(_('It runs the [StatusNet](http://status.net/) microblogging software, version %s, available under the [GNU Affero General Public License](http://www.fsf.org/licensing/licenses/agpl-3.0.html).'), STATUSNET_VERSION);
$output = common_markup_to_html($instr);
$this->raw($output);
{
$this->basicAuthProcessHeader();
- $realm = common_config('site', 'name') . ' API';
+ $realm = common_config('api', 'realm');
- if (!isset($this->auth_user_nickname) && $required) {
+ if (empty($realm)) {
+ $realm = common_config('site', 'name') . ' API';
+ }
+
+ if (empty($this->auth_user_nickname) && $required) {
header('WWW-Authenticate: Basic realm="' . $realm . '"');
// show error if the user clicks 'cancel'
}
}
+class CLIChannel extends Channel
+{
+ function source()
+ {
+ return 'cli';
+ }
+
+ function output($user, $text)
+ {
+ $site = common_config('site', 'name');
+ print "[{$user->nickname}@{$site}] $text\n";
+ }
+
+ function error($user, $text)
+ {
+ $this->output($user, $text);
+ }
+}
+
class XMPPChannel extends Channel
{
<?php
/*
* StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, StatusNet, Inc.
+ * Copyright (C) 2008, 2009, 2010 StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
$this->user = $user;
}
- function execute($channel)
+ /**
+ * Execute the command and send success or error results
+ * back via the given communications channel.
+ *
+ * @param Channel
+ */
+ public function execute($channel)
+ {
+ try {
+ $this->handle($channel);
+ } catch (CommandException $e) {
+ $channel->error($this->user, $e->getMessage());
+ } catch (Exception $e) {
+ common_log(LOG_ERR, "Error handling " . get_class($this) . ": " . $e->getMessage());
+ $channel->error($this->user, $e->getMessage());
+ }
+ }
+
+
+ /**
+ * Override this with the meat!
+ *
+ * An error to send back to the user may be sent by throwing
+ * a CommandException with a formatted message.
+ *
+ * @param Channel
+ * @throws CommandException
+ */
+ function handle($channel)
{
return false;
}
+
+ /**
+ * Look up a notice from an argument, by poster's name to get last post
+ * or notice_id prefixed with #.
+ *
+ * @return Notice
+ * @throws CommandException
+ */
+ function getNotice($arg)
+ {
+ $notice = null;
+ if (Event::handle('StartCommandGetNotice', array($this, $arg, &$notice))) {
+ if(substr($this->other,0,1)=='#'){
+ // A specific notice_id #123
+
+ $notice = Notice::staticGet(substr($arg,1));
+ if (!$notice) {
+ throw new CommandException(_('Notice with that id does not exist'));
+ }
+ }
+
+ if (Validate::uri($this->other)) {
+ // A specific notice by URI lookup
+ $notice = Notice::staticGet('uri', $arg);
+ }
+
+ if (!$notice) {
+ // Local or remote profile name to get their last notice.
+ // May throw an exception and report 'no such user'
+ $recipient = $this->getProfile($arg);
+
+ $notice = $recipient->getCurrentNotice();
+ if (!$notice) {
+ throw new CommandException(_('User has no last notice'));
+ }
+ }
+ }
+ Event::handle('EndCommandGetNotice', array($this, $arg, &$notice));
+ if (!$notice) {
+ throw new CommandException(_('Notice with that id does not exist'));
+ }
+ return $notice;
+ }
+
+ /**
+ * Look up a local or remote profile by nickname.
+ *
+ * @return Profile
+ * @throws CommandException
+ */
+ function getProfile($arg)
+ {
+ $profile = null;
+ if (Event::handle('StartCommandGetProfile', array($this, $arg, &$profile))) {
+ $profile =
+ common_relative_profile($this->user, common_canonical_nickname($arg));
+ }
+ Event::handle('EndCommandGetProfile', array($this, $arg, &$profile));
+ if (!$profile) {
+ throw new CommandException(sprintf(_('Could not find a user with nickname %s'), $arg));
+ }
+ return $profile;
+ }
+
+ /**
+ * Get a local user by name
+ * @return User
+ * @throws CommandException
+ */
+ function getUser($arg)
+ {
+ $user = null;
+ if (Event::handle('StartCommandGetUser', array($this, $arg, &$user))) {
+ $user = User::staticGet('nickname', $arg);
+ }
+ Event::handle('EndCommandGetUser', array($this, $arg, &$user));
+ if (!$user){
+ throw new CommandException(sprintf(_('Could not find a local user with nickname %s'),
+ $arg));
+ }
+ return $user;
+ }
+
+ /**
+ * Get a local or remote group by name.
+ * @return User_group
+ * @throws CommandException
+ */
+ function getGroup($arg)
+ {
+ $group = null;
+ if (Event::handle('StartCommandGetGroup', array($this, $arg, &$group))) {
+ $group = User_group::getForNickname($arg, $this->user->getProfile());
+ }
+ Event::handle('EndCommandGetGroup', array($this, $arg, &$group));
+ if (!$group) {
+ throw new CommandException(_('No such group.'));
+ }
+ return $group;
+ }
+}
+
+class CommandException extends Exception
+{
}
class UnimplementedCommand extends Command
{
- function execute($channel)
+ function handle($channel)
{
$channel->error($this->user, _("Sorry, this command is not yet implemented."));
}
parent::__construct($user);
$this->other = $other;
}
- function execute($channel)
+
+ function handle($channel)
{
- $recipient = User::staticGet('nickname', $this->other);
- if(! $recipient){
- $channel->error($this->user, sprintf(_('Could not find a user with nickname %s'),
- $this->other));
- }else{
- if ($recipient->id == $this->user->id) {
- $channel->error($this->user, _('It does not make a lot of sense to nudge yourself!'));
- }else{
- if ($recipient->email && $recipient->emailnotifynudge) {
- mail_notify_nudge($this->user, $recipient);
- }
- // XXX: notify by IM
- // XXX: notify by SMS
- $channel->output($this->user, sprintf(_('Nudge sent to %s'),
- $recipient->nickname));
+ $recipient = $this->getUser($this->other);
+ if ($recipient->id == $this->user->id) {
+ throw new CommandException(_('It does not make a lot of sense to nudge yourself!'));
+ } else {
+ if ($recipient->email && $recipient->emailnotifynudge) {
+ mail_notify_nudge($this->user, $recipient);
}
+ // XXX: notify by IM
+ // XXX: notify by SMS
+ $channel->output($this->user, sprintf(_('Nudge sent to %s'),
+ $recipient->nickname));
}
}
}
class StatsCommand extends Command
{
- function execute($channel)
+ function handle($channel)
{
$profile = $this->user->getProfile();
$this->other = $other;
}
- function execute($channel)
+ function handle($channel)
{
- if(substr($this->other,0,1)=='#'){
- //favoriting a specific notice_id
-
- $notice = Notice::staticGet(substr($this->other,1));
- if (!$notice) {
- $channel->error($this->user, _('Notice with that id does not exist'));
- return;
- }
- $recipient = $notice->getProfile();
- }else{
- //favoriting a given user's last notice
-
- $recipient =
- common_relative_profile($this->user, common_canonical_nickname($this->other));
-
- if (!$recipient) {
- $channel->error($this->user, _('No such user.'));
- return;
- }
- $notice = $recipient->getCurrentNotice();
- if (!$notice) {
- $channel->error($this->user, _('User has no last notice'));
- return;
- }
- }
-
+ $notice = $this->getNotice($this->other);
$fave = Fave::addNew($this->user, $notice);
if (!$fave) {
return;
}
- $other = User::staticGet('id', $recipient->id);
+ // @fixme favorite notification should be triggered
+ // at a lower level
+
+ $other = User::staticGet('id', $notice->profile_id);
if ($other && $other->id != $user->id) {
if ($other->email && $other->emailnotifyfav) {
}
}
+
class JoinCommand extends Command
{
var $other = null;
$this->other = $other;
}
- function execute($channel)
+ function handle($channel)
{
-
- $nickname = common_canonical_nickname($this->other);
- $group = User_group::staticGet('nickname', $nickname);
- $cur = $this->user;
-
- if (!$group) {
- $channel->error($cur, _('No such group.'));
- return;
- }
+ $group = $this->getGroup($this->other);
+ $cur = $this->user;
if ($cur->isMember($group)) {
$channel->error($cur, _('You are already a member of that group'));
$this->other = $other;
}
- function execute($channel)
+ function handle($channel)
{
-
- $nickname = common_canonical_nickname($this->other);
- $group = User_group::staticGet('nickname', $nickname);
- $cur = $this->user;
+ $group = $this->getGroup($this->other);
+ $cur = $this->user;
if (!$group) {
$channel->error($cur, _('No such group.'));
$this->other = $other;
}
- function execute($channel)
+ function handle($channel)
{
- $recipient =
- common_relative_profile($this->user, common_canonical_nickname($this->other));
-
- if (!$recipient) {
- $channel->error($this->user, _('No such user.'));
- return;
- }
+ $recipient = $this->getProfile($this->other);
$whois = sprintf(_("%1\$s (%2\$s)"), $recipient->nickname,
$recipient->profileurl);
$this->text = $text;
}
- function execute($channel)
+ function handle($channel)
{
- $other = User::staticGet('nickname', common_canonical_nickname($this->other));
+ try {
+ $other = $this->getUser($this->other);
+ } catch (CommandException $e) {
+ try {
+ $profile = $this->getProfile($this->other);
+ } catch (CommandException $f) {
+ throw $e;
+ }
+ throw new CommandException(sprintf(_('%s is a remote profile; you can only send direct messages to users on the same server.'), $this->other));
+ }
$len = mb_strlen($this->text);
$this->other = $other;
}
- function execute($channel)
+ function handle($channel)
{
- if(substr($this->other,0,1)=='#'){
- //repeating a specific notice_id
-
- $notice = Notice::staticGet(substr($this->other,1));
- if (!$notice) {
- $channel->error($this->user, _('Notice with that id does not exist'));
- return;
- }
- $recipient = $notice->getProfile();
- }else{
- //repeating a given user's last notice
-
- $recipient =
- common_relative_profile($this->user, common_canonical_nickname($this->other));
-
- if (!$recipient) {
- $channel->error($this->user, _('No such user.'));
- return;
- }
- $notice = $recipient->getCurrentNotice();
- if (!$notice) {
- $channel->error($this->user, _('User has no last notice'));
- return;
- }
- }
+ $notice = $this->getNotice($this->other);
if($this->user->id == $notice->profile_id)
{
return;
}
- if ($recipient->hasRepeated($notice->id)) {
+ if ($this->user->getProfile()->hasRepeated($notice->id)) {
$channel->error($this->user, _('Already repeated that notice'));
return;
}
$this->text = $text;
}
- function execute($channel)
+ function handle($channel)
{
- if(substr($this->other,0,1)=='#'){
- //replying to a specific notice_id
-
- $notice = Notice::staticGet(substr($this->other,1));
- if (!$notice) {
- $channel->error($this->user, _('Notice with that id does not exist'));
- return;
- }
- $recipient = $notice->getProfile();
- }else{
- //replying to a given user's last notice
-
- $recipient =
- common_relative_profile($this->user, common_canonical_nickname($this->other));
-
- if (!$recipient) {
- $channel->error($this->user, _('No such user.'));
- return;
- }
- $notice = $recipient->getCurrentNotice();
- if (!$notice) {
- $channel->error($this->user, _('User has no last notice'));
- return;
- }
- }
+ $notice = $this->getNotice($this->other);
+ $recipient = $notice->getProfile();
$len = mb_strlen($this->text);
$this->other = $other;
}
- function execute($channel)
+ function handle($channel)
{
- $target_nickname = common_canonical_nickname($this->other);
-
- $target =
- common_relative_profile($this->user, $target_nickname);
+ $target = $this->getProfile($this->other);
- if (!$target) {
- $channel->error($this->user, _('No such user.'));
- return;
- }
$notice = $target->getCurrentNotice();
if (!$notice) {
$channel->error($this->user, _('User has no last notice'));
}
$notice_content = $notice->content;
- $channel->output($this->user, $target_nickname . ": " . $notice_content);
+ $channel->output($this->user, $target->nickname . ": " . $notice_content);
}
}
$this->other = $other;
}
- function execute($channel)
+ function handle($channel)
{
if (!$this->other) {
return;
}
- $otherUser = User::staticGet('nickname', $this->other);
+ $target = $this->getProfile($this->other);
- if (empty($otherUser)) {
- $channel->error($this->user, _('No such user'));
- return;
+ $remote = Remote_profile::staticGet('id', $target->id);
+ if ($remote) {
+ throw new CommandException(_("Can't subscribe to OMB profiles by command."));
}
try {
Subscription::start($this->user->getProfile(),
- $otherUser->getProfile());
+ $target);
$channel->output($this->user, sprintf(_('Subscribed to %s'), $this->other));
} catch (Exception $e) {
$channel->error($this->user, $e->getMessage());
$this->other = $other;
}
- function execute($channel)
+ function handle($channel)
{
if(!$this->other) {
$channel->error($this->user, _('Specify the name of the user to unsubscribe from'));
return;
}
- $otherUser = User::staticGet('nickname', $this->other);
-
- if (empty($otherUser)) {
- $channel->error($this->user, _('No such user'));
- }
+ $target = $this->getProfile($this->other);
try {
Subscription::cancel($this->user->getProfile(),
- $otherUser->getProfile());
+ $target);
$channel->output($this->user, sprintf(_('Unsubscribed from %s'), $this->other));
} catch (Exception $e) {
$channel->error($this->user, $e->getMessage());
parent::__construct($user);
$this->other = $other;
}
- function execute($channel)
+ function handle($channel)
{
if ($other) {
$channel->error($this->user, _("Command not yet implemented."));
$this->other = $other;
}
- function execute($channel)
+ function handle($channel)
{
if ($other) {
$channel->error($this->user, _("Command not yet implemented."));
class LoginCommand extends Command
{
- function execute($channel)
+ function handle($channel)
{
$disabled = common_config('logincommand','disabled');
$disabled = isset($disabled) && $disabled;
class SubscriptionsCommand extends Command
{
- function execute($channel)
+ function handle($channel)
{
$profile = $this->user->getSubscriptions(0);
$nicknames=array();
class SubscribersCommand extends Command
{
- function execute($channel)
+ function handle($channel)
{
$profile = $this->user->getSubscribers();
$nicknames=array();
class GroupsCommand extends Command
{
- function execute($channel)
+ function handle($channel)
{
$group = $this->user->getGroups();
$groups=array();
class HelpCommand extends Command
{
- function execute($channel)
+ function handle($channel)
{
$channel->output($this->user,
_("Commands:\n".
array('crawldelay' => 0,
'disallow' => array('main', 'settings', 'admin', 'search', 'message')
),
+ 'api' =>
+ array('realm' => null),
);
/**
* Build an XMPP proxy connection that'll save outgoing messages
* to the 'xmppout' queue to be picked up by xmppdaemon later.
+ *
+ * If queueing is disabled, we'll grab a live connection.
+ *
+ * @return XMPPHP
*/
function jabber_proxy()
{
- $proxy = new Queued_XMPP(common_config('xmpp', 'host') ?
- common_config('xmpp', 'host') :
- common_config('xmpp', 'server'),
- common_config('xmpp', 'port'),
- common_config('xmpp', 'user'),
- common_config('xmpp', 'password'),
- common_config('xmpp', 'resource') . 'daemon',
- common_config('xmpp', 'server'),
- common_config('xmpp', 'debug') ?
- true : false,
- common_config('xmpp', 'debug') ?
- XMPPHP_Log::LEVEL_VERBOSE : null);
- return $proxy;
+ if (common_config('queue', 'enabled')) {
+ $proxy = new Queued_XMPP(common_config('xmpp', 'host') ?
+ common_config('xmpp', 'host') :
+ common_config('xmpp', 'server'),
+ common_config('xmpp', 'port'),
+ common_config('xmpp', 'user'),
+ common_config('xmpp', 'password'),
+ common_config('xmpp', 'resource') . 'daemon',
+ common_config('xmpp', 'server'),
+ common_config('xmpp', 'debug') ?
+ true : false,
+ common_config('xmpp', 'debug') ?
+ XMPPHP_Log::LEVEL_VERBOSE : null);
+ return $proxy;
+ } else {
+ return jabber_connect();
+ }
}
/**
*/
public function __construct($host, $port, $user, $password, $resource, $server = null, $printlog = false, $loglevel = null)
{
- parent::__construct($host, $port, $user, $password, $resource, $server, $printlog, $loglevel);
- // Normally the fulljid isn't filled out until resource binding time;
- // we need to save it here since we're not talking to a real server.
- $this->fulljid = "{$this->basejid}/{$this->resource}";
+ parent::__construct($host, $port, $user, $password, $resource, $server, $printlog, $loglevel);
+
+ // We use $host to connect, but $server to build JIDs if specified.
+ // This seems to fix an upstream bug where $host was used to build
+ // $this->basejid, never seen since it isn't actually used in the base
+ // classes.
+ if (!$server) {
+ $server = $this->host;
+ }
+ $this->basejid = $this->user . '@' . $server;
+
+ // Normally the fulljid is filled out by the server at resource binding
+ // time, but we need to do it since we're not talking to a real server.
+ $this->fulljid = "{$this->basejid}/{$this->resource}";
}
/**
{
mb_internal_encoding('UTF-8');
- // gettext seems very picky... We first need to setlocale()
- // to a locale which _does_ exist on the system, and _then_
- // we can set in another locale that may not be set up
- // (say, ga_ES for Galego/Galician) it seems to take it.
- common_init_locale("en_US");
-
// Note that this setlocale() call may "fail" but this is harmless;
// gettext will still select the right language.
$language = common_language();
$locale_set = common_init_locale($language);
+ if (!$locale_set) {
+ // The requested locale doesn't exist on the system.
+ //
+ // gettext seems very picky... We first need to setlocale()
+ // to a locale which _does_ exist on the system, and _then_
+ // we can set in another locale that may not be set up
+ // (say, ga_ES for Galego/Galician) it seems to take it.
+ //
+ // For some reason C and POSIX which are guaranteed to work
+ // don't do the job. en_US.UTF-8 should be there most of the
+ // time, but not guaranteed.
+ $ok = common_init_locale("en_US");
+ if (!$ok) {
+ // Try to find a complete, working locale...
+ // @fixme shelling out feels awfully inefficient
+ // but I don't think there's a more standard way.
+ $all = `locale -a`;
+ foreach (explode("\n", $all) as $locale) {
+ if (preg_match('/\.utf[-_]?8$/i', $locale)) {
+ $ok = setlocale(LC_ALL, $locale);
+ if ($ok) {
+ break;
+ }
+ }
+ }
+ if (!$ok) {
+ common_log(LOG_ERR, "Unable to find a UTF-8 locale on this system; UI translations may not work.");
+ }
+ }
+ $locale_set = common_init_locale($language);
+ }
+
setlocale(LC_CTYPE, 'C');
// So we do not have to make people install the gettext locales
$path = common_config('site','locale_path');
function common_check_user($nickname, $password)
{
+ // empty nickname always unacceptable
+ if (empty($nickname)) {
+ return false;
+ }
+
$authenticatedUser = false;
if (Event::handle('StartCheckPassword', array($nickname, $password, &$authenticatedUser))) {
protected $site = null;
protected $pingid = 0;
protected $lastping = null;
+ protected $conn = null;
static protected $singletons = array();
return true;
}
+ /**
+ * Allow remote profile references to be used in commands:
+ * sub update@status.net
+ * whois evan@identi.ca
+ * reply http://identi.ca/evan hey what's up
+ *
+ * @param Command $command
+ * @param string $arg
+ * @param Profile &$profile
+ * @return hook return code
+ */
+ function onStartCommandGetProfile($command, $arg, &$profile)
+ {
+ $oprofile = $this->pullRemoteProfile($arg);
+ if ($oprofile && !$oprofile->isGroup()) {
+ $profile = $oprofile->localProfile();
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Allow remote group references to be used in commands:
+ * join group+statusnet@identi.ca
+ * join http://identi.ca/group/statusnet
+ * drop identi.ca/group/statusnet
+ *
+ * @param Command $command
+ * @param string $arg
+ * @param User_group &$group
+ * @return hook return code
+ */
+ function onStartCommandGetGroup($command, $arg, &$group)
+ {
+ $oprofile = $this->pullRemoteProfile($arg);
+ if ($oprofile && $oprofile->isGroup()) {
+ $group = $oprofile->localGroup();
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ protected function pullRemoteProfile($arg)
+ {
+ $oprofile = null;
+ if (preg_match('!^((?:\w+\.)*\w+@(?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+)$!', $arg)) {
+ // webfinger lookup
+ try {
+ return Ostatus_profile::ensureWebfinger($arg);
+ } catch (Exception $e) {
+ common_log(LOG_ERR, 'Webfinger lookup failed for ' .
+ $arg . ': ' . $e->getMessage());
+ }
+ }
+
+ // Look for profile URLs, with or without scheme:
+ $urls = array();
+ if (preg_match('!^https?://((?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+(?:/\w+)+)$!', $arg)) {
+ $urls[] = $arg;
+ }
+ if (preg_match('!^((?:\w+\.)*\w+(?:\w+\-\w+)*\.\w+(?:/\w+)+)$!', $arg)) {
+ $schemes = array('http', 'https');
+ foreach ($schemes as $scheme) {
+ $urls[] = "$scheme://$arg";
+ }
+ }
+
+ foreach ($urls as $url) {
+ try {
+ return Ostatus_profile::ensureProfile($url);
+ } catch (Exception $e) {
+ common_log(LOG_ERR, 'Profile lookup failed for ' .
+ $arg . ': ' . $e->getMessage());
+ }
+ }
+ return null;
+ }
+
/**
* Make sure necessary tables are filled out.
*/
// Any existing query string parameters must be preserved
$url = $this->callback;
- if (strpos('?', $url) !== false) {
+ if (strpos($url, '?') !== false) {
$url .= '&';
} else {
$url .= '?';
function initFromResponse($response)
{
if (!$response->isOk()) {
- throw new FeedSubBadResponseException($response->getCode());
+ throw new FeedSubBadResponseException($response->getStatus());
}
$sourceurl = $response->getUrl();
function notify($profile)
{
$feed = common_path('api/statuses/user_timeline/') .
- $profile->nickname . '.rss';
+ $profile->id . '.rss';
$cloudSub = new RSSCloudSubscription();
function userFromFeed($feed)
{
- // We only do profile feeds
+ // We only do canonical RSS2 profile feeds (specified by ID), e.g.:
+ // http://www.example.com/api/statuses/user_timeline/2.rss
$path = common_path('api/statuses/user_timeline/');
- $valid = '%^' . $path . '(?<nickname>.*)\.rss$%';
+ $valid = '%^' . $path . '(?<id>.*)\.rss$%';
if (preg_match($valid, $feed, $matches)) {
- $user = User::staticGet('nickname', $matches['nickname']);
+ $user = User::staticGet('id', $matches['id']);
if (!empty($user)) {
return $user;
}
Todo:
-* make email field required on registration form
* add a more visible indicator that validation is still outstanding
-* localization for UI strings
* test with XMPP, API posting
$user = User::staticGet('id', $notice->profile_id);
if (!empty($user)) { // it's a remote notice
if (!$this->validated($user)) {
- throw new ClientException(_("You must validate your email address before posting."));
+ throw new ClientException(_m("You must validate your email address before posting."));
}
}
return true;
}
+ /**
+ * Event handler for registration attempts; rejects the registration
+ * if email field is missing.
+ *
+ * @param RegisterAction $action
+ * @return bool hook result code
+ */
+ function onStartRegistrationTry($action)
+ {
+ $email = $action->trimmed('email');
+
+ if (empty($email)) {
+ $action->showForm(_m('You must provide an email address to register.'));
+ return false;
+ }
+
+ // Default form will run address format validation and reject if bad.
+
+ return true;
+ }
+
/**
* Check if a user has a validated email address or has been
* otherwise grandfathered in.
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-03-10 10:05-0800\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: RequireValidatedEmailPlugin.php:57
+msgid "You must validate your email address before posting."
+msgstr ""
+
+#: RequireValidatedEmailPlugin.php:75
+msgid "You must provide an email address to register."
+msgstr ""
+
+#: RequireValidatedEmailPlugin.php:128
+msgid ""
+"The Require Validated Email plugin disables posting for accounts that do not "
+"have a validated email address."
+msgstr ""
--- /dev/null
+#!/usr/bin/env php
+<?php
+/*
+ * StatusNet - a distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, 2010 StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
+
+$shortoptions = 'i:n:';
+$longoptions = array('id=', 'nickname=');
+
+$helptext = <<<END_OF_USERROLE_HELP
+command.php [options] [command line]
+Perform commands on behalf of a user, such as sub, unsub, join, drop
+
+ -i --id ID of the user
+ -n --nickname nickname of the user
+
+END_OF_USERROLE_HELP;
+
+require_once INSTALLDIR.'/scripts/commandline.inc';
+
+
+
+function interpretCommand($user, $body)
+{
+ $inter = new CommandInterpreter();
+ $chan = new CLIChannel();
+ $cmd = $inter->handle_command($user, $body);
+ if ($cmd) {
+ $cmd->execute($chan);
+ return true;
+ } else {
+ $chan->error($user, "Not a valid command. Try 'help'?");
+ return false;
+ }
+}
+
+
+
+if (have_option('i', 'id')) {
+ $id = get_option_value('i', 'id');
+ $user = User::staticGet('id', $id);
+ if (empty($user)) {
+ print "Can't find user with ID $id\n";
+ exit(1);
+ }
+} else if (have_option('n', 'nickname')) {
+ $nickname = get_option_value('n', 'nickname');
+ $user = User::staticGet('nickname', $nickname);
+ if (empty($user)) {
+ print "Can't find user with nickname '$nickname'\n";
+ exit(1);
+ }
+} else {
+ print "You must provide either an ID or a nickname.\n\n";
+ print $helptext;
+ exit(1);
+}
+
+// @todo refactor the interactive console in console.php and use
+// that to optionally make an interactive test console here too.
+// Would be good to help people test commands when XMPP or email
+// isn't available locally.
+interpretCommand($user, implode(' ', $args));
+
--- /dev/null
+#!/usr/bin/env php
+<?php
+/*
+ * StatusNet - a distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
+
+$shortoptions = 'd';
+$longoptions = array('delete');
+
+$helptext = <<<END_OF_FLUSHSITE_HELP
+flushsite.php -s<sitename>
+Flush the site with the given name from memcached.
+
+END_OF_FLUSHSITE_HELP;
+
+require_once INSTALLDIR.'/scripts/commandline.inc';
+
+$nickname = common_config('site', 'nickname');
+
+$sn = Status_network::memGet('nickname', $nickname);
+
+if (empty($sn)) {
+ print "No such site.\n";
+ exit(-1);
+}
+
+print "Flushing cache for {$nickname}...";
+$sn->decache();
+print "OK.\n";
\ No newline at end of file