function handlePost()
{
- if (empty($this->scoped) ||
- $this->target->sameAs($this->scoped)) {
+ if (!$this->scoped instanceof Profile ||
+ !$this->target->sameAs($this->scoped)) {
// 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.'), 403);
}
$activity = new Activity($dom->documentElement);
- $saved = null;
+ common_debug('AtomPub: Ignoring right now, but this POST was made to collection: '.$activity->id);
- if (Event::handle('StartAtomPubNewActivity', array(&$activity, $this->target->getUser(), &$saved))) {
- if ($activity->verb != ActivityVerb::POST) {
- // TRANS: Client error displayed when not using the POST verb. Do not translate POST.
- $this->clientError(_('Can only handle POST activities.'));
- }
-
- $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));
- }
-
- $saved = $this->postNote($activity);
-
- Event::handle('EndAtomPubNewActivity', array($activity, $this->target->getUser(), $saved));
- }
-
- if (!empty($saved)) {
- header('HTTP/1.1 201 Created');
- header("Location: " . common_local_url('ApiStatusesShow', array('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.
- // TRANS: %d is the notice ID (number).
- $this->clientError(sprintf(_('No content for notice %d.'), $note->id));
- }
-
- // Get (safe!) HTML and text versions of the content
-
- $rendered = common_purify($sourceContent);
- $content = common_strip_html($rendered);
-
- $shortened = $this->target->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)
+ // Reset activity data so we can handle it in the same functions as with OStatus
+ // because we don't let clients set their own UUIDs... Not sure what AtomPub thinks
+ // about that though.
+ $activity->id = null;
+ $activity->actor = null; // not used anyway, we use $this->target
+ $activity->objects[0]->id = null;
- common_debug("Note ID is {$note->id}");
-
- if (!empty($note->id)) {
- $notice = Notice::getKV('uri', trim($note->id));
-
- if (!empty($notice)) {
- // TRANS: Client error displayed when using another format than AtomPub.
- // TRANS: %s is the notice URI.
- $this->clientError(sprintf(_('Notice with URI "%s" already exists.'), $note->id));
- }
- common_log(LOG_NOTICE, "Saving client-supplied notice URI '$note->id'");
- $options['uri'] = $note->id;
+ $stored = null;
+ if (Event::handle('StartAtomPubNewActivity', array($activity, $this->target, &$stored))) {
+ // TRANS: Client error displayed when not using the POST verb. Do not translate POST.
+ throw new ClientException(_('Could not handle this Atom Activity.'));
}
-
- // 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);
+ if (!$stored instanceof Notice) {
+ throw new ServerException('Server did not create a Notice object from handled AtomPub activity.');
}
+ Event::handle('EndAtomPubNewActivity', array($activity, $this->target, $stored));
- // Check for optional attributes...
-
- if ($activity->context instanceof ActivityContext) {
-
- foreach ($activity->context->attention as $uri=>$type) {
- try {
- $profile = Profile::fromUri($uri);
- if ($profile->isGroup()) {
- $options['groups'][] = $profile->id;
- } else {
- $options['replies'][] = $uri;
- }
- } catch (UnknownUriException $e) {
- 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::getKV('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->target->getID(),
- $content,
- 'atompub', // TODO: deal with this
- $options);
-
- return $saved;
+ header('HTTP/1.1 201 Created');
+ header("Location: " . common_local_url('ApiStatusesShow', array('id' => $stored->getID(),
+ 'format' => 'atom')));
+ $this->showSingleAtomStatus($stored);
}
}