summaryrefslogtreecommitdiff
path: root/actions
diff options
context:
space:
mode:
authorBrion Vibber <brion@pobox.com>2010-12-07 10:50:05 -0800
committerBrion Vibber <brion@pobox.com>2010-12-07 10:50:05 -0800
commit9df856e667a12cd217576263efbc72fff12692d9 (patch)
treedc8d588e8b01d1ec788c78d6aec10a9b9d26bec6 /actions
parent01f32e3998b8d031d2a39e2d0506253142b6632e (diff)
parent4b4b763255ad3b2bff8f18da2bd3927b52a54e55 (diff)
Merge branch '0.9.x' into merge
Conflicts: README actions/hostmeta.php classes/File_redirection.php lib/common.php lib/designsettings.php lib/router.php lib/util.php lib/xmppmanager.php plugins/OStatus/OStatusPlugin.php
Diffstat (limited to 'actions')
-rw-r--r--actions/allrss.php2
-rw-r--r--actions/apiatomservice.php100
-rw-r--r--actions/apidirectmessagenew.php2
-rw-r--r--actions/apifriendshipsexists.php2
-rw-r--r--actions/apigroupcreate.php33
-rw-r--r--actions/apioauthauthorize.php2
-rw-r--r--actions/apisearchatom.php6
-rw-r--r--actions/apisearchjson.php7
-rw-r--r--actions/apistatusesshow.php62
-rw-r--r--actions/apistatusesupdate.php2
-rw-r--r--actions/apitimelineuser.php310
-rw-r--r--actions/editgroup.php15
-rw-r--r--actions/emailsettings.php205
-rw-r--r--actions/favorited.php28
-rw-r--r--actions/hostmeta.php5
-rw-r--r--actions/newgroup.php19
-rw-r--r--actions/newmessage.php2
-rw-r--r--actions/newnotice.php2
-rw-r--r--actions/oembed.php19
-rw-r--r--actions/profilesettings.php16
-rw-r--r--actions/register.php11
-rw-r--r--actions/rsd.php14
-rw-r--r--actions/shownotice.php30
-rw-r--r--actions/userxrd.php65
24 files changed, 737 insertions, 222 deletions
diff --git a/actions/allrss.php b/actions/allrss.php
index d398c8a6a..573bb4eb2 100644
--- a/actions/allrss.php
+++ b/actions/allrss.php
@@ -56,6 +56,8 @@ class AllrssAction extends Rss10Action
* @param array $args Web and URL arguments
*
* @return boolean false if user doesn't exist
+ *
+ */
function prepare($args)
{
parent::prepare($args);
diff --git a/actions/apiatomservice.php b/actions/apiatomservice.php
new file mode 100644
index 000000000..fb9d6aee8
--- /dev/null
+++ b/actions/apiatomservice.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * An AtomPub service document for a user
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link http://status.net/
+ */
+
+require_once INSTALLDIR.'/lib/apibareauth.php';
+
+/**
+ * Shows an AtomPub service document for a user
+ *
+ * @category API
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3
+ * @link http://status.net/
+ */
+
+class ApiAtomServiceAction extends ApiBareAuthAction
+{
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ $this->user = $this->getTargetUser($this->arg('id'));
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user.'), 404, $this->format);
+ return;
+ }
+
+ return true;
+ }
+
+ /**
+ * Handle the arguments. In our case, show a service document.
+ *
+ * @param Array $args unused.
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ header('Content-Type: application/atomsvc+xml');
+
+ $this->startXML();
+ $this->elementStart('service', array('xmlns' => 'http://www.w3.org/2007/app',
+ 'xmlns:atom' => 'http://www.w3.org/2005/Atom'));
+ $this->elementStart('workspace');
+ $this->element('atom:title', null, _('Main'));
+ $this->elementStart('collection',
+ array('href' => common_local_url('ApiTimelineUser',
+ array('id' => $this->user->id,
+ 'format' => 'atom'))));
+ $this->element('atom:title',
+ null,
+ sprintf(_("%s timeline"),
+ $this->user->nickname));
+ $this->element('accept', null, 'application/atom+xml;type=entry');
+ $this->elementEnd('collection');
+ $this->elementEnd('workspace');
+ $this->elementEnd('service');
+ $this->endXML();
+ }
+}
diff --git a/actions/apidirectmessagenew.php b/actions/apidirectmessagenew.php
index b335a9c93..978c75353 100644
--- a/actions/apidirectmessagenew.php
+++ b/actions/apidirectmessagenew.php
@@ -119,7 +119,7 @@ class ApiDirectMessageNewAction extends ApiAuthAction
$this->format
);
} else {
- $content_shortened = common_shorten_links($this->content);
+ $content_shortened = $this->auth_user->shortenLinks($this->content);
if (Message::contentTooLong($content_shortened)) {
$this->clientError(
// TRANS: Client error displayed when message content is too long.
diff --git a/actions/apifriendshipsexists.php b/actions/apifriendshipsexists.php
index c8766633b..43b1daf4f 100644
--- a/actions/apifriendshipsexists.php
+++ b/actions/apifriendshipsexists.php
@@ -85,7 +85,7 @@ class ApiFriendshipsExistsAction extends ApiPrivateAuthAction
if (empty($this->profile_a) || empty($this->profile_b)) {
$this->clientError(
// TRANS: Client error displayed when supplying invalid parameters to an API call checking if a friendship exists.
- _('Two valid IDs or screen_names must be supplied.'),
+ _('Two valid IDs or nick names must be supplied.'),
400,
$this->format
);
diff --git a/actions/apigroupcreate.php b/actions/apigroupcreate.php
index 54875a718..d01504bc8 100644
--- a/actions/apigroupcreate.php
+++ b/actions/apigroupcreate.php
@@ -73,7 +73,7 @@ class ApiGroupCreateAction extends ApiAuthAction
$this->user = $this->auth_user;
- $this->nickname = $this->arg('nickname');
+ $this->nickname = Nickname::normalize($this->arg('nickname'));
$this->fullname = $this->arg('full_name');
$this->homepage = $this->arg('homepage');
$this->description = $this->arg('description');
@@ -150,26 +150,7 @@ class ApiGroupCreateAction extends ApiAuthAction
*/
function validateParams()
{
- $valid = Validate::string(
- $this->nickname, array(
- 'min_length' => 1,
- 'max_length' => 64,
- 'format' => NICKNAME_FMT
- )
- );
-
- if (!$valid) {
- $this->clientError(
- // TRANS: Validation error in form for group creation.
- _(
- 'Nickname must have only lowercase letters ' .
- 'and numbers and no spaces.'
- ),
- 403,
- $this->format
- );
- return false;
- } elseif ($this->groupNicknameExists($this->nickname)) {
+ if ($this->groupNicknameExists($this->nickname)) {
$this->clientError(
// TRANS: Client error trying to create a group with a nickname this is already in use.
_('Nickname already in use. Try another one.'),
@@ -265,15 +246,7 @@ class ApiGroupCreateAction extends ApiAuthAction
foreach ($this->aliases as $alias) {
- $valid = Validate::string(
- $alias, array(
- 'min_length' => 1,
- 'max_length' => 64,
- 'format' => NICKNAME_FMT
- )
- );
-
- if (!$valid) {
+ if (!Nickname::isValid($alias)) {
$this->clientError(
// TRANS: Client error shown when providing an invalid alias during group creation.
// TRANS: %s is the invalid alias.
diff --git a/actions/apioauthauthorize.php b/actions/apioauthauthorize.php
index b2c0de719..d76ae060f 100644
--- a/actions/apioauthauthorize.php
+++ b/actions/apioauthauthorize.php
@@ -421,7 +421,7 @@ class ApiOauthAuthorizeAction extends Action
if ($this->app->name == 'anonymous') {
// Special message for the anonymous app and consumer.
// TRANS: User notification of external application requesting account access.
- // TRANS: %3$s is the access type requested, %4$s is the StatusNet sitename.
+ // TRANS: %3$s is the access type requested (read-write or read-only), %4$s is the StatusNet sitename.
$msg = _('An application would like the ability ' .
'to <strong>%3$s</strong> your %4$s account data. ' .
'You should only give access to your %4$s account ' .
diff --git a/actions/apisearchatom.php b/actions/apisearchatom.php
index 6743e92c8..32ff918da 100644
--- a/actions/apisearchatom.php
+++ b/actions/apisearchatom.php
@@ -114,7 +114,7 @@ class ApiSearchAtomAction extends ApiPrivateAuthAction
$this->page = 1;
}
- // TODO: Suppport since_id -- we need to tweak the backend
+ // TODO: Suppport max_id -- we need to tweak the backend
// Search classes to support it.
$this->since_id = $this->trimmed('since_id');
@@ -177,6 +177,10 @@ class ApiSearchAtomAction extends ApiPrivateAuthAction
$this->max_id = $notice->id;
}
+ if ($this->since_id && $notice->id <= $this->since_id) {
+ break;
+ }
+
if ($cnt > $this->rpp) {
break;
}
diff --git a/actions/apisearchjson.php b/actions/apisearchjson.php
index 38e612ee3..dd442b7f2 100644
--- a/actions/apisearchjson.php
+++ b/actions/apisearchjson.php
@@ -85,6 +85,9 @@ class ApiSearchJSONAction extends ApiPrivateAuthAction
$this->page = 1;
}
+ // TODO: Suppport max_id -- we need to tweak the backend
+ // Search classes to support it.
+
$this->since_id = $this->trimmed('since_id');
$this->geocode = $this->trimmed('geocode');
@@ -127,9 +130,9 @@ class ApiSearchJSONAction extends ApiPrivateAuthAction
$cnt = $notice->find();
}
- // TODO: since_id, lang, geocode
+ // TODO: max_id, lang, geocode
- $results = new JSONSearchResultsList($notice, $q, $this->rpp, $this->page);
+ $results = new JSONSearchResultsList($notice, $q, $this->rpp, $this->page, $this->since_id);
$this->initDocument('json');
$results->show();
diff --git a/actions/apistatusesshow.php b/actions/apistatusesshow.php
index a98e45f79..e684a07ee 100644
--- a/actions/apistatusesshow.php
+++ b/actions/apistatusesshow.php
@@ -100,13 +100,23 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
{
parent::handle($args);
- if (!in_array($this->format, array('xml', 'json'))) {
+ if (!in_array($this->format, array('xml', 'json', 'atom'))) {
// TRANS: Client error displayed when trying to handle an unknown API method.
- $this->clientError(_('API method not found.'), $code = 404);
+ $this->clientError(_('API method not found.'), 404);
return;
}
- $this->showNotice();
+ switch ($_SERVER['REQUEST_METHOD']) {
+ case 'GET':
+ $this->showNotice();
+ break;
+ case 'DELETE':
+ $this->deleteNotice();
+ break;
+ default:
+ $this->clientError(_('HTTP method not supported.'), 405);
+ return;
+ }
}
/**
@@ -117,10 +127,18 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
function showNotice()
{
if (!empty($this->notice)) {
- if ($this->format == 'xml') {
+ switch ($this->format) {
+ case 'xml':
$this->showSingleXmlStatus($this->notice);
- } elseif ($this->format == 'json') {
+ break;
+ case 'json':
$this->show_single_json_status($this->notice);
+ break;
+ case 'atom':
+ $this->showSingleAtomStatus($this->notice);
+ break;
+ default:
+ throw new Exception(sprintf(_("Unsupported format: %s"), $this->format));
}
} else {
// XXX: Twitter just sets a 404 header and doens't bother
@@ -153,9 +171,14 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
*
* @return boolean true
*/
+
function isReadOnly($args)
{
- return true;
+ if ($_SERVER['REQUEST_METHOD'] == 'GET') {
+ return true;
+ } else {
+ return false;
+ }
}
/**
@@ -197,4 +220,31 @@ class ApiStatusesShowAction extends ApiPrivateAuthAction
return null;
}
+
+ function deleteNotice()
+ {
+ if ($this->format != 'atom') {
+ $this->clientError(_("Can only delete using the Atom format."));
+ return;
+ }
+
+ if (empty($this->auth_user) ||
+ ($this->notice->profile_id != $this->auth_user->id &&
+ !$this->auth_user->hasRight(Right::DELETEOTHERSNOTICE))) {
+ $this->clientError(_('Can\'t delete this notice.'), 403);
+ return;
+ }
+
+ if (Event::handle('StartDeleteOwnNotice', array($this->auth_user, $this->notice))) {
+ $this->notice->delete();
+ Event::handle('EndDeleteOwnNotice', array($this->auth_user, $this->notice));
+ }
+
+ // @fixme is there better output we could do here?
+
+ header('HTTP/1.1 200 OK');
+ header('Content-Type: text/plain');
+ print(sprintf(_('Deleted notice %d'), $this->notice->id));
+ print("\n");
+ }
}
diff --git a/actions/apistatusesupdate.php b/actions/apistatusesupdate.php
index 1a3b54900..a8ec7f8bb 100644
--- a/actions/apistatusesupdate.php
+++ b/actions/apistatusesupdate.php
@@ -231,7 +231,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction
return;
}
- $status_shortened = common_shorten_links($this->status);
+ $status_shortened = $this->auth_user->shortenlinks($this->status);
if (Notice::contentTooLong($status_shortened)) {
// Note: Twitter truncates anything over 140, flags the status
diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php
index 0046c462d..d90507aa4 100644
--- a/actions/apitimelineuser.php
+++ b/actions/apitimelineuser.php
@@ -97,7 +97,12 @@ class ApiTimelineUserAction extends ApiBareAuthAction
function handle($args)
{
parent::handle($args);
- $this->showTimeline();
+
+ if ($this->isPost()) {
+ $this->handlePost();
+ } else {
+ $this->showTimeline();
+ }
}
/**
@@ -114,9 +119,9 @@ class ApiTimelineUserAction extends ApiBareAuthAction
$atom = new AtomUserNoticeFeed($this->user, $this->auth_user);
$link = common_local_url(
- 'showstream',
- array('nickname' => $this->user->nickname)
- );
+ 'showstream',
+ array('nickname' => $this->user->nickname)
+ );
$self = $this->getSelfUri();
@@ -132,20 +137,63 @@ class ApiTimelineUserAction extends ApiBareAuthAction
break;
case 'rss':
$this->showRssTimeline(
- $this->notices,
- $atom->title,
- $link,
- $atom->subtitle,
- $suplink,
- $atom->logo,
- $self
- );
+ $this->notices,
+ $atom->title,
+ $link,
+ $atom->subtitle,
+ $suplink,
+ $atom->logo,
+ $self
+ );
break;
case 'atom':
header('Content-Type: application/atom+xml; charset=utf-8');
$atom->setId($self);
$atom->setSelfLink($self);
+
+ // Add navigation links: next, prev, first
+ // Note: we use IDs rather than pages for navigation; page boundaries
+ // change too quickly!
+
+ if (!empty($this->next_id)) {
+ $nextUrl = common_local_url('ApiTimelineUser',
+ array('format' => 'atom',
+ 'id' => $this->user->id),
+ array('max_id' => $this->next_id));
+
+ $atom->addLink($nextUrl,
+ array('rel' => 'next',
+ 'type' => 'application/atom+xml'));
+ }
+
+ if (($this->page > 1 || !empty($this->max_id)) && !empty($this->notices)) {
+
+ $lastNotice = $this->notices[0];
+ $lastId = $lastNotice->id;
+
+ $prevUrl = common_local_url('ApiTimelineUser',
+ array('format' => 'atom',
+ 'id' => $this->user->id),
+ array('since_id' => $lastId));
+
+ $atom->addLink($prevUrl,
+ array('rel' => 'prev',
+ 'type' => 'application/atom+xml'));
+ }
+
+ if ($this->page > 1 || !empty($this->since_id) || !empty($this->max_id)) {
+
+ $firstUrl = common_local_url('ApiTimelineUser',
+ array('format' => 'atom',
+ 'id' => $this->user->id));
+
+ $atom->addLink($firstUrl,
+ array('rel' => 'first',
+ 'type' => 'application/atom+xml'));
+
+ }
+
$atom->addEntryFromNotices($this->notices);
$this->raw($atom->getString());
@@ -169,13 +217,18 @@ class ApiTimelineUserAction extends ApiBareAuthAction
{
$notices = array();
- $notice = $this->user->getNotices(
- ($this->page-1) * $this->count, $this->count,
- $this->since_id, $this->max_id
- );
+ $notice = $this->user->getNotices(($this->page-1) * $this->count,
+ $this->count + 1,
+ $this->since_id,
+ $this->max_id);
while ($notice->fetch()) {
- $notices[] = clone($notice);
+ if (count($notices) < $this->count) {
+ $notices[] = clone($notice);
+ } else {
+ $this->next_id = $notice->id;
+ break;
+ }
}
return $notices;
@@ -188,9 +241,14 @@ class ApiTimelineUserAction extends ApiBareAuthAction
*
* @return boolean true
*/
+
function isReadOnly($args)
{
- return true;
+ if ($_SERVER['REQUEST_METHOD'] == 'GET') {
+ return true;
+ } else {
+ return false;
+ }
}
/**
@@ -221,17 +279,215 @@ class ApiTimelineUserAction extends ApiBareAuthAction
$last = count($this->notices) - 1;
return '"' . implode(
- ':',
- array($this->arg('action'),
- common_user_cache_hash($this->auth_user),
- common_language(),
- $this->user->id,
- strtotime($this->notices[0]->created),
- strtotime($this->notices[$last]->created))
- )
- . '"';
+ ':',
+ array($this->arg('action'),
+ common_user_cache_hash($this->auth_user),
+ common_language(),
+ $this->user->id,
+ strtotime($this->notices[0]->created),
+ strtotime($this->notices[$last]->created))
+ )
+ . '"';
}
return null;
}
+
+ function handlePost()
+ {
+ if (empty($this->auth_user) ||
+ $this->auth_user->id != $this->user->id) {
+ // TRANS: Client error displayed trying to add a notice to another user's timeline.
+ $this->clientError(_('Only the user can add to their own timeline.'));
+ return;
+ }
+
+ // Only handle posts for Atom
+ if ($this->format != 'atom') {
+ // TRANS: Client error displayed when using another format than AtomPub.
+ $this->clientError(_('Only accept AtomPub for Atom feeds.'));
+ return;
+ }
+
+ $xml = file_get_contents('php://input');
+
+ $dom = DOMDocument::loadXML($xml);
+
+ if ($dom->documentElement->namespaceURI != Activity::ATOM ||
+ $dom->documentElement->localName != 'entry') {
+ // TRANS: Client error displayed when not using an Atom entry.
+ $this->clientError(_('Atom post must be an Atom entry.'));
+ return;
+ }
+
+ $activity = new Activity($dom->documentElement);
+
+ if (Event::handle('StartAtomPubNewActivity', array(&$activity))) {
+
+ if ($activity->verb != ActivityVerb::POST) {
+ // TRANS: Client error displayed when not using the POST verb.
+ // TRANS: Do not translate POST.
+ $this->clientError(_('Can only handle POST activities.'));
+ return;
+ }
+
+ $note = $activity->objects[0];
+
+ if (!in_array($note->type, array(ActivityObject::NOTE,
+ ActivityObject::BLOGENTRY,
+ ActivityObject::STATUS))) {
+ // TRANS: Client error displayed when using an unsupported activity object type.
+ // TRANS: %s is the unsupported activity object type.
+ $this->clientError(sprintf(_('Cannot handle activity object type "%s".'),
+ $note->type));
+ return;
+ }
+
+ $saved = $this->postNote($activity);
+
+ Event::handle('EndAtomPubNewActivity', array($activity, $saved));
+ }
+
+ if (!empty($saved)) {
+ header("Location: " . common_local_url('ApiStatusesShow', array('notice_id' => $saved->id,
+ 'format' => 'atom')));
+ $this->showSingleAtomStatus($saved);
+ }
+ }
+
+ function postNote($activity)
+ {
+ $note = $activity->objects[0];
+
+ // Use summary as fallback for content
+
+ if (!empty($note->content)) {
+ $sourceContent = $note->content;
+ } else if (!empty($note->summary)) {
+ $sourceContent = $note->summary;
+ } else if (!empty($note->title)) {
+ $sourceContent = $note->title;
+ } else {
+ // @fixme fetch from $sourceUrl?
+ // TRANS: Client error displayed when posting a notice without content through the API.
+ $this->clientError(sprintf(_('No content for notice %d.'),
+ $note->id));
+ return;
+ }
+
+ // Get (safe!) HTML and text versions of the content
+
+ $rendered = $this->purify($sourceContent);
+ $content = html_entity_decode(strip_tags($rendered), ENT_QUOTES, 'UTF-8');
+
+ $shortened = $this->auth_user->shortenLinks($content);
+
+ $options = array('is_local' => Notice::LOCAL_PUBLIC,
+ 'rendered' => $rendered,
+ 'replies' => array(),
+ 'groups' => array(),
+ 'tags' => array(),
+ 'urls' => array());
+
+ // accept remote URI (not necessarily a good idea)
+
+ common_debug("Note ID is {$note->id}");
+
+ if (!empty($note->id)) {
+ $notice = Notice::staticGet('uri', trim($note->id));
+
+ if (!empty($notice)) {
+ // TRANS: Client error displayed when using another format than AtomPub.
+ $this->clientError(sprintf(_('Notice with URI "%s" already exists.'),
+ $note->id));
+ return;
+ }
+ common_log(LOG_NOTICE, "Saving client-supplied notice URI '$note->id'");
+ $options['uri'] = $note->id;
+ }
+
+ // accept remote create time (also maybe not such a good idea)
+
+ if (!empty($activity->time)) {
+ common_log(LOG_NOTICE, "Saving client-supplied create time {$activity->time}");
+ $options['created'] = common_sql_date($activity->time);
+ }
+
+ // Check for optional attributes...
+
+ if (!empty($activity->context)) {
+
+ foreach ($activity->context->attention as $uri) {
+
+ $profile = Profile::fromURI($uri);
+
+ if (!empty($profile)) {
+ $options['replies'] = $uri;
+ } else {
+ $group = User_group::staticGet('uri', $uri);
+ if (!empty($group)) {
+ $options['groups'] = $uri;
+ } else {
+ // @fixme: hook for discovery here
+ common_log(LOG_WARNING, sprintf(_('AtomPub post with unknown attention URI %s'), $uri));
+ }
+ }
+ }
+
+ // Maintain direct reply associations
+ // @fixme what about conversation ID?
+
+ if (!empty($activity->context->replyToID)) {
+ $orig = Notice::staticGet('uri',
+ $activity->context->replyToID);
+ if (!empty($orig)) {
+ $options['reply_to'] = $orig->id;
+ }
+ }
+
+ $location = $activity->context->location;
+
+ if ($location) {
+ $options['lat'] = $location->lat;
+ $options['lon'] = $location->lon;
+ if ($location->location_id) {
+ $options['location_ns'] = $location->location_ns;
+ $options['location_id'] = $location->location_id;
+ }
+ }
+ }
+
+ // Atom categories <-> hashtags
+
+ foreach ($activity->categories as $cat) {
+ if ($cat->term) {
+ $term = common_canonical_tag($cat->term);
+ if ($term) {
+ $options['tags'][] = $term;
+ }
+ }
+ }
+
+ // Atom enclosures -> attachment URLs
+ foreach ($activity->enclosures as $href) {
+ // @fixme save these locally or....?
+ $options['urls'][] = $href;
+ }
+
+ $saved = Notice::saveNew($this->user->id,
+ $content,
+ 'atompub', // TODO: deal with this
+ $options);
+
+ return $saved;
+ }
+
+ function purify($content)
+ {
+ require_once INSTALLDIR.'/extlib/htmLawed/htmLawed.php';
+
+ $config = array('safe' => 1,
+ 'deny_attribute' => 'id,style,on*');
+ return htmLawed($content, $config);
+ }
}
diff --git a/actions/editgroup.php b/actions/editgroup.php
index 4d3af34c7..ab4dbb283 100644
--- a/actions/editgroup.php
+++ b/actions/editgroup.php
@@ -177,21 +177,14 @@ class EditgroupAction extends GroupDesignAction
return;
}
- $nickname = common_canonical_nickname($this->trimmed('nickname'));
+ $nickname = Nickname::normalize($this->trimmed('nickname'));
$fullname = $this->trimmed('fullname');
$homepage = $this->trimmed('homepage');
$description = $this->trimmed('description');
$location = $this->trimmed('location');
$aliasstring = $this->trimmed('aliases');
- if (!Validate::string($nickname, array('min_length' => 1,
- 'max_length' => 64,
- 'format' => NICKNAME_FMT))) {
- // TRANS: Group edit form validation error.
- $this->showForm(_('Nickname must have only lowercase letters '.
- 'and numbers and no spaces.'));
- return;
- } else if ($this->nicknameExists($nickname)) {
+ if ($this->nicknameExists($nickname)) {
// TRANS: Group edit form validation error.
$this->showForm(_('Nickname already in use. Try another one.'));
return;
@@ -241,9 +234,7 @@ class EditgroupAction extends GroupDesignAction
}
foreach ($aliases as $alias) {
- if (!Validate::string($alias, array('min_length' => 1,
- 'max_length' => 64,
- 'format' => NICKNAME_FMT))) {
+ if (!Nickname::isValid($alias)) {
// TRANS: Group edit form validation error.
$this->showForm(sprintf(_('Invalid alias: "%s"'), $alias));
return;
diff --git a/actions/emailsettings.php b/actions/emailsettings.php
index 9c250fc8a..4a7dc1b87 100644
--- a/actions/emailsettings.php
+++ b/actions/emailsettings.php
@@ -79,6 +79,7 @@ class EmailsettingsAction extends AccountSettingsAction
function showScripts()
{
parent::showScripts();
+ $this->script('emailsettings.js');
$this->autofocus('email');
}
@@ -149,6 +150,26 @@ class EmailsettingsAction extends AccountSettingsAction
$this->elementStart('fieldset', array('id' => 'settings_email_incoming'));
// TRANS: Form legend for incoming e-mail settings form.
$this->element('legend', null, _('Incoming email'));
+
+ $this->elementStart('ul', 'form_data');
+ $this->elementStart('li');
+ $this->checkbox('emailpost',
+ // TRANS: Checkbox label in e-mail preferences form.
+ _('I want to post notices by email.'),
+ $user->emailpost);
+ $this->elementEnd('li');
+ $this->elementEnd('ul');
+
+ // Our stylesheets make the form_data list items all floats, which
+ // creates lots of problems with trying to wrap divs around things.
+ // This should force a break before the next section, which needs
+ // to be separate so we can disable the things in it when the
+ // checkbox is off.
+ $this->elementStart('div', array('style' => 'clear: both'));
+ $this->elementEnd('div');
+
+ $this->elementStart('div', array('id' => 'emailincoming'));
+
if ($user->incomingemail) {
$this->elementStart('p');
$this->element('span', 'address', $user->incomingemail);
@@ -163,13 +184,22 @@ class EmailsettingsAction extends AccountSettingsAction
}
$this->elementStart('p');
- $this->element('span', 'input_instructions',
- // TRANS: Instructions for incoming e-mail address input form.
- _('Make a new email address for posting to; '.
- 'cancels the old one.'));
+ if ($user->incomingemail) {
+ // TRANS: Instructions for incoming e-mail address input form, when an address has already been assigned.
+ $msg = _('Make a new email address for posting to; '.
+ 'cancels the old one.');
+ } else {
+ // TRANS: Instructions for incoming e-mail address input form.
+ $msg = _('To send notices via email, we need to create a unique email address for you on this server:');
+ }
+ $this->element('span', 'input_instructions', $msg);
$this->elementEnd('p');
+
// TRANS: Button label for adding an e-mail address to send notices from.
$this->submit('newincoming', _m('BUTTON','New'));
+
+ $this->elementEnd('div'); // div#emailincoming
+
$this->elementEnd('fieldset');
}
@@ -178,51 +208,47 @@ class EmailsettingsAction extends AccountSettingsAction
$this->element('legend', null, _('Email preferences'));
$this->elementStart('ul', 'form_data');
- $this->elementStart('li');
- $this->checkbox('emailnotifysub',
- // TRANS: Checkbox label in e-mail preferences form.
- _('Send me notices of new subscriptions through email.'),
- $user->emailnotifysub);
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->checkbox('emailnotifyfav',
- // TRANS: Checkbox label in e-mail preferences form.
- _('Send me email when someone '.
- 'adds my notice as a favorite.'),
- $user->emailnotifyfav);
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->checkbox('emailnotifymsg',
- // TRANS: Checkbox label in e-mail preferences form.
- _('Send me email when someone sends me a private message.'),
- $user->emailnotifymsg);
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->checkbox('emailnotifyattn',
- // TRANS: Checkbox label in e-mail preferences form.
- _('Send me email when someone sends me an "@-reply".'),
- $user->emailnotifyattn);
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->checkbox('emailnotifynudge',
- // TRANS: Checkbox label in e-mail preferences form.
- _('Allow friends to nudge me and send me an email.'),
- $user->emailnotifynudge);
- $this->elementEnd('li');
- if (common_config('emailpost', 'enabled')) {
- $this->elementStart('li');
- $this->checkbox('emailpost',
- // TRANS: Checkbox label in e-mail preferences form.
- _('I want to post notices by email.'),
- $user->emailpost);
- $this->elementEnd('li');
- }
- $this->elementStart('li');
- $this->checkbox('emailmicroid',
- // TRANS: Checkbox label in e-mail preferences form.
- _('Publish a MicroID for my email address.'),
- $user->emailmicroid);
- $this->elementEnd('li');
+
+ if (Event::handle('StartEmailFormData', array($this))) {
+ $this->elementStart('li');
+ $this->checkbox('emailnotifysub',
+ // TRANS: Checkbox label in e-mail preferences form.
+ _('Send me notices of new subscriptions through email.'),
+ $user->emailnotifysub);
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->checkbox('emailnotifyfav',
+ // TRANS: Checkbox label in e-mail preferences form.
+ _('Send me email when someone '.
+ 'adds my notice as a favorite.'),
+ $user->emailnotifyfav);
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->checkbox('emailnotifymsg',
+ // TRANS: Checkbox label in e-mail preferences form.
+ _('Send me email when someone sends me a private message.'),
+ $user->emailnotifymsg);
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->checkbox('emailnotifyattn',
+ // TRANS: Checkbox label in e-mail preferences form.
+ _('Send me email when someone sends me an "@-reply".'),
+ $user->emailnotifyattn);
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->checkbox('emailnotifynudge',
+ // TRANS: Checkbox label in e-mail preferences form.
+ _('Allow friends to nudge me and send me an email.'),
+ $user->emailnotifynudge);
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->checkbox('emailmicroid',
+ // TRANS: Checkbox label in e-mail preferences form.
+ _('Publish a MicroID for my email address.'),
+ $user->emailmicroid);
+ $this->elementEnd('li');
+ Event::handle('EndEmailFormData', array($this));
+ }
$this->elementEnd('ul');
// TRANS: Button label to save e-mail preferences.
$this->submit('save', _m('BUTTON','Save'));
@@ -299,43 +325,48 @@ class EmailsettingsAction extends AccountSettingsAction
function savePreferences()
{
- $emailnotifysub = $this->boolean('emailnotifysub');
- $emailnotifyfav = $this->boolean('emailnotifyfav');
- $emailnotifymsg = $this->boolean('emailnotifymsg');
- $emailnotifynudge = $this->boolean('emailnotifynudge');
- $emailnotifyattn = $this->boolean('emailnotifyattn');
- $emailmicroid = $this->boolean('emailmicroid');
- $emailpost = $this->boolean('emailpost');
-
- $user = common_current_user();
-
- assert(!is_null($user)); // should already be checked
-
- $user->query('BEGIN');
-
- $original = clone($user);
-
- $user->emailnotifysub = $emailnotifysub;
- $user->emailnotifyfav = $emailnotifyfav;
- $user->emailnotifymsg = $emailnotifymsg;
- $user->emailnotifynudge = $emailnotifynudge;
- $user->emailnotifyattn = $emailnotifyattn;
- $user->emailmicroid = $emailmicroid;
- $user->emailpost = $emailpost;
-
- $result = $user->update($original);
-
- if ($result === false) {
- common_log_db_error($user, 'UPDATE', __FILE__);
- // TRANS: Server error thrown on database error updating e-mail preferences.
- $this->serverError(_('Couldn\'t update user.'));
- return;
- }
-
- $user->query('COMMIT');
-
- // TRANS: Confirmation message for successful e-mail preferences save.
- $this->showForm(_('Email preferences saved.'), true);
+ $user = common_current_user();
+
+ if (Event::handle('StartEmailSaveForm', array($this, &$user))) {
+
+ $emailnotifysub = $this->boolean('emailnotifysub');
+ $emailnotifyfav = $this->boolean('emailnotifyfav');
+ $emailnotifymsg = $this->boolean('emailnotifymsg');
+ $emailnotifynudge = $this->boolean('emailnotifynudge');
+ $emailnotifyattn = $this->boolean('emailnotifyattn');
+ $emailmicroid = $this->boolean('emailmicroid');
+ $emailpost = $this->boolean('emailpost');
+
+ assert(!is_null($user)); // should already be checked
+
+ $user->query('BEGIN');
+
+ $original = clone($user);
+
+ $user->emailnotifysub = $emailnotifysub;
+ $user->emailnotifyfav = $emailnotifyfav;
+ $user->emailnotifymsg = $emailnotifymsg;
+ $user->emailnotifynudge = $emailnotifynudge;
+ $user->emailnotifyattn = $emailnotifyattn;
+ $user->emailmicroid = $emailmicroid;
+ $user->emailpost = $emailpost;
+
+ $result = $user->update($original);
+
+ if ($result === false) {
+ common_log_db_error($user, 'UPDATE', __FILE__);
+ // TRANS: Server error thrown on database error updating e-mail preferences.
+ $this->serverError(_('Couldn\'t update user.'));
+ return;
+ }
+
+ $user->query('COMMIT');
+
+ Event::handle('EndEmailSaveForm', array($this));
+
+ // TRANS: Confirmation message for successful e-mail preferences save.
+ $this->showForm(_('Email preferences saved.'), true);
+ }
}
/**
@@ -501,6 +532,7 @@ class EmailsettingsAction extends AccountSettingsAction
$orig = clone($user);
$user->incomingemail = null;
+ $user->emailpost = 0;
if (!$user->updateKeys($orig)) {
common_log_db_error($user, 'UPDATE', __FILE__);
@@ -525,6 +557,7 @@ class EmailsettingsAction extends AccountSettingsAction
$orig = clone($user);
$user->incomingemail = mail_new_incoming_address();
+ $user->emailpost = 1;
if (!$user->updateKeys($orig)) {
common_log_db_error($user, 'UPDATE', __FILE__);
diff --git a/actions/favorited.php b/actions/favorited.php
index d8980440d..19d49feec 100644
--- a/actions/favorited.php
+++ b/actions/favorited.php
@@ -185,29 +185,11 @@ class FavoritedAction extends Action
function showContent()
{
- $weightexpr = common_sql_weight('fave.modified', common_config('popular', 'dropoff'));
- $cutoff = sprintf("fave.modified > '%s'",
- common_sql_date(time() - common_config('popular', 'cutoff')));
-
- $qry = 'SELECT notice.*, '.
- $weightexpr . ' as weight ' .
- 'FROM notice JOIN fave ON notice.id = fave.notice_id ' .
- "WHERE $cutoff " .
- 'GROUP BY id,profile_id,uri,content,rendered,url,created,notice.modified,reply_to,is_local,source,notice.conversation ' .
- 'ORDER BY weight DESC';
-
- $offset = ($this->page - 1) * NOTICES_PER_PAGE;
- $limit = NOTICES_PER_PAGE + 1;
-
- if (common_config('db', 'type') == 'pgsql') {
- $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
- } else {
- $qry .= ' LIMIT ' . $offset . ', ' . $limit;
- }
-
- $notice = Memcached_DataObject::cachedQuery('Notice',
- $qry,
- 600);
+ $pop = new Popularity();
+ $pop->offset = ($this->page - 1) * NOTICES_PER_PAGE;
+ $pop->limit = NOTICES_PER_PAGE;
+ $pop->expiry = 600;
+ $notice = $pop->getNotices();
$nl = new NoticeList($notice, $this);
diff --git a/actions/hostmeta.php b/actions/hostmeta.php
index b7beee5a8..331fc8a99 100644
--- a/actions/hostmeta.php
+++ b/actions/hostmeta.php
@@ -51,6 +51,11 @@ class HostMetaAction extends Action
$xrd->host = $domain;
if(Event::handle('StartHostMetaLinks', array(&$xrd->links))) {
+ $url = common_local_url('userxrd');
+ $url.= '?uri={uri}';
+ $xrd->links[] = array('rel' => Discovery::LRDD_REL,
+ 'template' => $url,
+ 'title' => array('Resource Descriptor'));
Event::handle('EndHostMetaLinks', array(&$xrd->links));
}
diff --git a/actions/newgroup.php b/actions/newgroup.php
index e0e7978c3..95af6415e 100644
--- a/actions/newgroup.php
+++ b/actions/newgroup.php
@@ -113,21 +113,18 @@ class NewgroupAction extends Action
function trySave()
{
- $nickname = $this->trimmed('nickname');
+ try {
+ $nickname = Nickname::normalize($this->trimmed('nickname'));
+ } catch (NicknameException $e) {
+ $this->showForm($e->getMessage());
+ }
$fullname = $this->trimmed('fullname');
$homepage = $this->trimmed('homepage');
$description = $this->trimmed('description');
$location = $this->trimmed('location');
$aliasstring = $this->trimmed('aliases');
- if (!Validate::string($nickname, array('min_length' => 1,
- 'max_length' => 64,
- 'format' => NICKNAME_FMT))) {
- // TRANS: Group create form validation error.
- $this->showForm(_('Nickname must have only lowercase letters '.
- 'and numbers and no spaces.'));
- return;
- } else if ($this->nicknameExists($nickname)) {
+ if ($this->nicknameExists($nickname)) {
// TRANS: Group create form validation error.
$this->showForm(_('Nickname already in use. Try another one.'));
return;
@@ -177,9 +174,7 @@ class NewgroupAction extends Action
}
foreach ($aliases as $alias) {
- if (!Validate::string($alias, array('min_length' => 1,
- 'max_length' => 64,
- 'format' => NICKNAME_FMT))) {
+ if (!Nickname::isValid($alias)) {
// TRANS: Group create form validation error.
$this->showForm(sprintf(_('Invalid alias: "%s"'), $alias));
return;
diff --git a/actions/newmessage.php b/actions/newmessage.php
index c58ed3849..447a00580 100644
--- a/actions/newmessage.php
+++ b/actions/newmessage.php
@@ -144,7 +144,7 @@ class NewmessageAction extends Action
$this->showForm(_('No content!'));
return;
} else {
- $content_shortened = common_shorten_links($this->content);
+ $content_shortened = $user->shortenLinks($this->content);
if (Message::contentTooLong($content_shortened)) {
// TRANS: Form validation error displayed when message content is too long.
diff --git a/actions/newnotice.php b/actions/newnotice.php
index 0d4dcfccd..faafd9551 100644
--- a/actions/newnotice.php
+++ b/actions/newnotice.php
@@ -154,7 +154,7 @@ class NewnoticeAction extends Action
return;
}
- $content_shortened = common_shorten_links($content);
+ $content_shortened = $user->shortenLinks($content);
if (Notice::contentTooLong($content_shortened)) {
// TRANS: Client error displayed when the parameter "status" is missing.
// TRANS: %d is the maximum number of character for a notice.
diff --git a/actions/oembed.php b/actions/oembed.php
index da3aa0c71..09d68a446 100644
--- a/actions/oembed.php
+++ b/actions/oembed.php
@@ -108,10 +108,23 @@ class OembedAction extends Action
$oembed['url']=$file_oembed->url;
}else if(substr($attachment->mimetype,0,strlen('image/'))=='image/'){
$oembed['type']='photo';
- //TODO set width and height
- //$oembed['width']=
- //$oembed['height']=
+ if ($attachment->filename) {
+ $filepath = File::path($attachment->filename);
+ $gis = @getimagesize($filepath);
+ if ($gis) {
+ $oembed['width'] = $gis[0];
+ $oembed['height'] = $gis[1];
+ } else {
+ // TODO Either throw an error or find a fallback?
+ }
+ }
$oembed['url']=$attachment->url;
+ $thumb = $attachment->getThumbnail();
+ if ($thumb) {
+ $oembed['thumbnail_url'] = $thumb->url;
+ $oembed['thumbnail_width'] = $thumb->width;
+ $oembed['thumbnail_height'] = $thumb->height;
+ }
}else{
$oembed['type']='link';
$oembed['url']=common_local_url('attachment',
diff --git a/actions/profilesettings.php b/actions/profilesettings.php
index e1a0f8b6d..28b1d20f3 100644
--- a/actions/profilesettings.php
+++ b/actions/profilesettings.php
@@ -225,7 +225,13 @@ class ProfilesettingsAction extends AccountSettingsAction
if (Event::handle('StartProfileSaveForm', array($this))) {
- $nickname = $this->trimmed('nickname');
+ try {
+ $nickname = Nickname::normalize($this->trimmed('nickname'));
+ } catch (NicknameException $e) {
+ $this->showForm($e->getMessage());
+ return;
+ }
+
$fullname = $this->trimmed('fullname');
$homepage = $this->trimmed('homepage');
$bio = $this->trimmed('bio');
@@ -236,13 +242,7 @@ class ProfilesettingsAction extends AccountSettingsAction
$tagstring = $this->trimmed('tags');
// Some validation
- if (!Validate::string($nickname, array('min_length' => 1,
- 'max_length' => 64,
- 'format' => NICKNAME_FMT))) {
- // TRANS: Validation error in form for profile settings.
- $this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.'));
- return;
- } else if (!User::allowed_nickname($nickname)) {
+ if (!User::allowed_nickname($nickname)) {
// TRANS: Validation error in form for profile settings.
$this->showForm(_('Not a valid nickname.'));
return;
diff --git a/actions/register.php b/actions/register.php
index a600dfe44..075b1af99 100644
--- a/actions/register.php
+++ b/actions/register.php
@@ -191,7 +191,11 @@ class RegisterAction extends Action
}
// Input scrubbing
- $nickname = common_canonical_nickname($nickname);
+ try {
+ $nickname = Nickname::normalize($nickname);
+ } catch (NicknameException $e) {
+ $this->showForm($e->getMessage());
+ }
$email = common_canonical_email($email);
if (!$this->boolean('license')) {
@@ -199,11 +203,6 @@ class RegisterAction extends Action
'agree to the license.'));
} else if ($email && !Validate::email($email, common_config('email', 'check_domain'))) {
$this->showForm(_('Not a valid email address.'));
- } else if (!Validate::string($nickname, array('min_length' => 1,
- 'max_length' => 64,
- 'format' => NICKNAME_FMT))) {
- $this->showForm(_('Nickname must have only lowercase letters '.
- 'and numbers and no spaces.'));
} else if ($this->nicknameExists($nickname)) {
$this->showForm(_('Nickname already in use. Try another one.'));
} else if (!User::allowed_nickname($nickname)) {
diff --git a/actions/rsd.php b/actions/rsd.php
index f88bf2e9a..e02c85c41 100644
--- a/actions/rsd.php
+++ b/actions/rsd.php
@@ -162,6 +162,20 @@ class RsdAction extends Action
'true');
$this->elementEnd('settings');
$this->elementEnd('api');
+
+ // Atom API
+
+ if (empty($this->user)) {
+ $service = common_local_url('ApiAtomService');
+ } else {
+ $service = common_local_url('ApiAtomService', array('id' => $this->user->nickname));
+ }
+
+ $this->element('api', array('name' => 'Atom',
+ 'preferred' => 'false',
+ 'apiLink' => $service,
+ 'blogID' => $blogID));
+
Event::handle('EndRsdListApis', array($this, $this->user));
}
$this->elementEnd('apis');
diff --git a/actions/shownotice.php b/actions/shownotice.php
index 653461731..91b0901bf 100644
--- a/actions/shownotice.php
+++ b/actions/shownotice.php
@@ -325,8 +325,38 @@ class SingleNoticeItem extends DoFollowListItem
$this->showEnd();
}
+ /**
+ * For our zoomed-in special case we'll use a fuller list
+ * for the attachment info.
+ */
function showNoticeAttachments() {
$al = new AttachmentList($this->notice, $this->out);
$al->show();
}
+
+ /**
+ * show the avatar of the notice's author
+ *
+ * We use the larger size for single notice page.
+ *
+ * @return void
+ */
+
+ function showAvatar()
+ {
+ $avatar_size = AVATAR_PROFILE_SIZE;
+
+ $avatar = $this->profile->getAvatar($avatar_size);
+
+ $this->out->element('img', array('src' => ($avatar) ?
+ $avatar->displayUrl() :
+ Avatar::defaultImage($avatar_size),
+ 'class' => 'avatar photo',
+ 'width' => $avatar_size,
+ 'height' => $avatar_size,
+ 'alt' =>
+ ($this->profile->fullname) ?
+ $this->profile->fullname :
+ $this->profile->nickname));
+ }
}
diff --git a/actions/userxrd.php b/actions/userxrd.php
new file mode 100644
index 000000000..582f7a35e
--- /dev/null
+++ b/actions/userxrd.php
@@ -0,0 +1,65 @@
+<?php
+/*
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+/**
+ * @package OStatusPlugin
+ * @maintainer James Walker <james@status.net>
+ */
+class UserxrdAction extends XrdAction
+{
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->uri = $this->trimmed('uri');
+ $this->uri = self::normalize($this->uri);
+
+ if (self::isWebfinger($this->uri)) {
+ $parts = explode('@', substr(urldecode($this->uri), 5));
+ if (count($parts) == 2) {
+ list($nick, $domain) = $parts;
+ // @fixme confirm the domain too
+ // @fixme if domain checking is added, ensure that it will not
+ // cause problems with sites that have changed domains!
+ $nick = common_canonical_nickname($nick);
+ $this->user = User::staticGet('nickname', $nick);
+ }
+ } else {
+ $this->user = User::staticGet('uri', $this->uri);
+ if (empty($this->user)) {
+ // try and get it by profile url
+ $profile = Profile::staticGet('profileurl', $this->uri);
+ if (!empty($profile)) {
+ $this->user = User::staticGet('id', $profile->id);
+ }
+ }
+ }
+
+ if (!$this->user) {
+ $this->clientError(_m('No such user.'), 404);
+ return false;
+ }
+
+ return true;
+ }
+}