diff options
Diffstat (limited to 'actions')
-rw-r--r-- | actions/apidirectmessage.php | 2 | ||||
-rw-r--r-- | actions/apifriendshipsdestroy.php | 9 | ||||
-rw-r--r-- | actions/apigrouplist.php | 2 | ||||
-rw-r--r-- | actions/apigrouplistall.php | 2 | ||||
-rw-r--r-- | actions/apitimelinefavorites.php | 71 | ||||
-rw-r--r-- | actions/apitimelinefriends.php | 76 | ||||
-rw-r--r-- | actions/apitimelinegroup.php | 76 | ||||
-rw-r--r-- | actions/apitimelinehome.php | 62 | ||||
-rw-r--r-- | actions/apitimelinementions.php | 36 | ||||
-rw-r--r-- | actions/apitimelinepublic.php | 29 | ||||
-rw-r--r-- | actions/apitimelineretweetedtome.php | 2 | ||||
-rw-r--r-- | actions/apitimelineretweetsofme.php | 38 | ||||
-rw-r--r-- | actions/apitimelinetag.php | 53 | ||||
-rw-r--r-- | actions/apitimelineuser.php | 62 | ||||
-rw-r--r-- | actions/doc.php | 7 | ||||
-rw-r--r-- | actions/favor.php | 2 | ||||
-rw-r--r-- | actions/groupmembers.php | 4 | ||||
-rw-r--r-- | actions/makeadmin.php | 3 | ||||
-rw-r--r-- | actions/public.php | 10 | ||||
-rw-r--r-- | actions/rsd.php | 226 | ||||
-rw-r--r-- | actions/showgroup.php | 4 | ||||
-rw-r--r-- | actions/showstream.php | 13 | ||||
-rw-r--r-- | actions/twitapisearchatom.php | 4 | ||||
-rw-r--r-- | actions/userauthorization.php | 21 |
24 files changed, 675 insertions, 139 deletions
diff --git a/actions/apidirectmessage.php b/actions/apidirectmessage.php index 5fbc46518..5355acf82 100644 --- a/actions/apidirectmessage.php +++ b/actions/apidirectmessage.php @@ -79,7 +79,7 @@ class ApiDirectMessageAction extends ApiAuthAction } $server = common_root_url(); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); if ($this->arg('sent')) { diff --git a/actions/apifriendshipsdestroy.php b/actions/apifriendshipsdestroy.php index 91c6fd032..d48a57756 100644 --- a/actions/apifriendshipsdestroy.php +++ b/actions/apifriendshipsdestroy.php @@ -124,12 +124,9 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction return; } - $result = subs_unsubscribe_user($this->user, $this->other->nickname); - - if (is_string($result)) { - $this->clientError($result, 403, $this->format); - return; - } + // throws an exception on error + Subscription::cancel($this->user->getProfile(), + $this->other->getProfile()); $this->initDocument($this->format); $this->showProfile($this->other, $this->format); diff --git a/actions/apigrouplist.php b/actions/apigrouplist.php index 66b67a030..605b38232 100644 --- a/actions/apigrouplist.php +++ b/actions/apigrouplist.php @@ -93,7 +93,7 @@ class ApiGroupListAction extends ApiBareAuthAction $sitename = common_config('site', 'name'); $title = sprintf(_("%s's groups"), $this->user->nickname); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $id = "tag:$taguribase:Groups"; $link = common_local_url( 'usergroups', diff --git a/actions/apigrouplistall.php b/actions/apigrouplistall.php index 1921c1f19..d2ef2978a 100644 --- a/actions/apigrouplistall.php +++ b/actions/apigrouplistall.php @@ -88,7 +88,7 @@ class ApiGroupListAllAction extends ApiPrivateAuthAction $sitename = common_config('site', 'name'); $title = sprintf(_("%s groups"), $sitename); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $id = "tag:$taguribase:Groups"; $link = common_local_url('groups'); $subtitle = sprintf(_("groups on %s"), $sitename); diff --git a/actions/apitimelinefavorites.php b/actions/apitimelinefavorites.php index 1027d97d4..c89d02247 100644 --- a/actions/apitimelinefavorites.php +++ b/actions/apitimelinefavorites.php @@ -100,44 +100,81 @@ class ApiTimelineFavoritesAction extends ApiBareAuthAction function showTimeline() { - $profile = $this->user->getProfile(); - $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); + $profile = $this->user->getProfile(); + $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); - $sitename = common_config('site', 'name'); - $title = sprintf( + $sitename = common_config('site', 'name'); + $title = sprintf( _('%1$s / Favorites from %2$s'), $sitename, $this->user->nickname ); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $id = "tag:$taguribase:Favorites:" . $this->user->id; - $link = common_local_url( - 'favorites', - array('nickname' => $this->user->nickname) - ); - $subtitle = sprintf( + + $subtitle = sprintf( _('%1$s updates favorited by %2$s / %2$s.'), $sitename, $profile->getBestName(), $this->user->nickname ); - $logo = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE); + $logo = !empty($avatar) + ? $avatar->displayUrl() + : Avatar::defaultImage(AVATAR_PROFILE_SIZE); switch($this->format) { case 'xml': $this->showXmlTimeline($this->notices); break; case 'rss': - $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $logo); + $link = common_local_url( + 'showfavorites', + array('nickname' => $this->user->nickname) + ); + $this->showRssTimeline( + $this->notices, + $title, + $link, + $subtitle, + null, + $logo + ); break; case 'atom': - $selfuri = common_root_url() . - ltrim($_SERVER['QUERY_STRING'], 'p='); - $this->showAtomTimeline( - $this->notices, $title, $id, $link, $subtitle, - null, $selfuri, $logo + + header('Content-Type: application/atom+xml; charset=utf-8'); + + $atom = new AtomNoticeFeed(); + + $atom->setId($id); + $atom->setTitle($title); + $atom->setSubtitle($subtitle); + $atom->setLogo($logo); + $atom->setUpdated('now'); + + $atom->addLink( + common_local_url( + 'showfavorites', + array('nickname' => $this->user->nickname) + ) + ); + + $id = $this->arg('id'); + $aargs = array('format' => 'atom'); + if (!empty($id)) { + $aargs['id'] = $id; + } + + $atom->addLink( + $this->getSelfUri('ApiTimelineFavorites', $aargs), + array('rel' => 'self', 'type' => 'application/atom+xml') ); + + $atom->addEntryFromNotices($this->notices); + + $this->raw($atom->getString()); + break; case 'json': $this->showJsonTimeline($this->notices); diff --git a/actions/apitimelinefriends.php b/actions/apitimelinefriends.php index 4e3827bae..2db76857e 100644 --- a/actions/apitimelinefriends.php +++ b/actions/apitimelinefriends.php @@ -112,41 +112,73 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); $sitename = common_config('site', 'name'); $title = sprintf(_("%s and friends"), $this->user->nickname); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $id = "tag:$taguribase:FriendsTimeline:" . $this->user->id; - $link = common_local_url( - 'all', array('nickname' => $this->user->nickname) - ); - $subtitle = sprintf( - _('Updates from %1$s and friends on %2$s!'), - $this->user->nickname, $sitename - ); - $logo = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE); + + $subtitle = sprintf( + _('Updates from %1$s and friends on %2$s!'), + $this->user->nickname, $sitename + ); + + $logo = (!empty($avatar)) + ? $avatar->displayUrl() + : Avatar::defaultImage(AVATAR_PROFILE_SIZE); switch($this->format) { case 'xml': $this->showXmlTimeline($this->notices); break; case 'rss': - $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $logo); + + $link = common_local_url( + 'all', array( + 'nickname' => $this->user->nickname + ) + ); + + $this->showRssTimeline( + $this->notices, + $title, + $link, + $subtitle, + null, + $logo + ); break; case 'atom': - $target_id = $this->arg('id'); + header('Content-Type: application/atom+xml; charset=utf-8'); + + $atom = new AtomNoticeFeed(); + + $atom->setId($id); + $atom->setTitle($title); + $atom->setSubtitle($subtitle); + $atom->setLogo($logo); + $atom->setUpdated('now'); - if (isset($target_id)) { - $selfuri = common_root_url() . - 'api/statuses/friends_timeline/' . - $target_id . '.atom'; - } else { - $selfuri = common_root_url() . - 'api/statuses/friends_timeline.atom'; + $atom->addLink( + common_local_url( + 'all', + array('nickname' => $this->user->nickname) + ) + ); + + $id = $this->arg('id'); + $aargs = array('format' => 'atom'); + if (!empty($id)) { + $aargs['id'] = $id; } - $this->showAtomTimeline( - $this->notices, $title, $id, $link, - $subtitle, null, $selfuri, $logo - ); + $atom->addLink( + $this->getSelfUri('ApiTimelineFriends', $aargs), + array('rel' => 'self', 'type' => 'application/atom+xml') + ); + + $atom->addEntryFromNotices($this->notices); + + $this->raw($atom->getString()); + break; case 'json': $this->showJsonTimeline($this->notices); diff --git a/actions/apitimelinegroup.php b/actions/apitimelinegroup.php index af414c680..1d0c4afdd 100644 --- a/actions/apitimelinegroup.php +++ b/actions/apitimelinegroup.php @@ -107,41 +107,85 @@ class ApiTimelineGroupAction extends ApiPrivateAuthAction $sitename = common_config('site', 'name'); $avatar = $this->group->homepage_logo; $title = sprintf(_("%s timeline"), $this->group->nickname); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $id = "tag:$taguribase:GroupTimeline:" . $this->group->id; - $link = common_local_url( - 'showgroup', - array('nickname' => $this->group->nickname) - ); + $subtitle = sprintf( _('Updates from %1$s on %2$s!'), $this->group->nickname, $sitename ); - $logo = ($avatar) ? $avatar : User_group::defaultLogo(AVATAR_PROFILE_SIZE); + + $logo = ($avatar) ? $avatar : User_group::defaultLogo(AVATAR_PROFILE_SIZE); switch($this->format) { case 'xml': $this->showXmlTimeline($this->notices); break; case 'rss': - $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $logo); - break; - case 'atom': - $selfuri = common_root_url() . - 'api/statusnet/groups/timeline/' . - $this->group->nickname . '.atom'; - $this->showAtomTimeline( + $this->showRssTimeline( $this->notices, $title, - $id, - $link, + $this->group->homeUrl(), $subtitle, null, - $selfuri, $logo ); break; + case 'atom': + + header('Content-Type: application/atom+xml; charset=utf-8'); + + try { + + // If this was called using an integer ID, i.e.: using the canonical + // URL for this group's feed, then pass the Group object into the feed, + // so the OStatus plugin, and possibly other plugins, can access it. + // Feels sorta hacky. -- Z + + $atom = null; + $id = $this->arg('id'); + + if (strval(intval($id)) === strval($id)) { + $atom = new AtomGroupNoticeFeed($this->group); + } else { + $atom = new AtomGroupNoticeFeed(); + } + + $atom->setId($id); + $atom->setTitle($title); + $atom->setSubtitle($subtitle); + $atom->setLogo($logo); + $atom->setUpdated('now'); + + $atom->addAuthorRaw($this->group->asAtomAuthor()); + $atom->setActivitySubject($this->group->asActivitySubject()); + + $atom->addLink($this->group->homeUrl()); + + $id = $this->arg('id'); + $aargs = array('format' => 'atom'); + if (!empty($id)) { + $aargs['id'] = $id; + } + + $atom->addLink( + $this->getSelfUri('ApiTimelineGroup', $aargs), + array('rel' => 'self', 'type' => 'application/atom+xml') + ); + + $atom->addEntryFromNotices($this->notices); + + $this->raw($atom->getString()); + + } catch (Atom10FeedException $e) { + $this->serverError( + 'Could not generate feed for group - ' . $e->getMessage() + ); + return; + } + + break; case 'json': $this->showJsonTimeline($this->notices); break; diff --git a/actions/apitimelinehome.php b/actions/apitimelinehome.php index 828eae6cf..0c72f4020 100644 --- a/actions/apitimelinehome.php +++ b/actions/apitimelinehome.php @@ -113,41 +113,69 @@ class ApiTimelineHomeAction extends ApiBareAuthAction $avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE); $sitename = common_config('site', 'name'); $title = sprintf(_("%s and friends"), $this->user->nickname); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $id = "tag:$taguribase:HomeTimeline:" . $this->user->id; - $link = common_local_url( - 'all', array('nickname' => $this->user->nickname) - ); + $subtitle = sprintf( _('Updates from %1$s and friends on %2$s!'), $this->user->nickname, $sitename ); - $logo = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_PROFILE_SIZE); + + $logo = (!empty($avatar)) + ? $avatar->displayUrl() + : Avatar::defaultImage(AVATAR_PROFILE_SIZE); switch($this->format) { case 'xml': $this->showXmlTimeline($this->notices); break; case 'rss': - $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $logo); + $link = common_local_url( + 'all', + array('nickname' => $this->user->nickname) + ); + $this->showRssTimeline( + $this->notices, + $title, + $link, + $subtitle, + null, + $logo + ); break; case 'atom': - $target_id = $this->arg('id'); + header('Content-Type: application/atom+xml; charset=utf-8'); + + $atom = new AtomNoticeFeed(); - if (isset($target_id)) { - $selfuri = common_root_url() . - 'api/statuses/home_timeline/' . - $target_id . '.atom'; - } else { - $selfuri = common_root_url() . - 'api/statuses/home_timeline.atom'; + $atom->setId($id); + $atom->setTitle($title); + $atom->setSubtitle($subtitle); + $atom->setLogo($logo); + $atom->setUpdated('now'); + + $atom->addLink( + common_local_url( + 'all', + array('nickname' => $this->user->nickname) + ) + ); + + $id = $this->arg('id'); + $aargs = array('format' => 'atom'); + if (!empty($id)) { + $aargs['id'] = $id; } - $this->showAtomTimeline( - $this->notices, $title, $id, $link, - $subtitle, null, $selfuri, $logo + $atom->addLink( + $this->getSelfUri('ApiTimelineHome', $aargs), + array('rel' => 'self', 'type' => 'application/atom+xml') ); + + $atom->addEntryFromNotices($this->notices); + $this->raw($atom->getString()); + break; case 'json': $this->showJsonTimeline($this->notices); diff --git a/actions/apitimelinementions.php b/actions/apitimelinementions.php index 9dc2162cc..a39c63346 100644 --- a/actions/apitimelinementions.php +++ b/actions/apitimelinementions.php @@ -117,7 +117,7 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction _('%1$s / Updates mentioning %2$s'), $sitename, $this->user->nickname ); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $id = "tag:$taguribase:Mentions:" . $this->user->id; $link = common_local_url( 'replies', @@ -137,12 +137,36 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $logo); break; case 'atom': - $selfuri = common_root_url() . - ltrim($_SERVER['QUERY_STRING'], 'p='); - $this->showAtomTimeline( - $this->notices, $title, $id, $link, $subtitle, - null, $selfuri, $logo + + $atom = new AtomNoticeFeed(); + + $atom->setId($id); + $atom->setTitle($title); + $atom->setSubtitle($subtitle); + $atom->setLogo($logo); + $atom->setUpdated('now'); + + $atom->addLink( + common_local_url( + 'replies', + array('nickname' => $this->user->nickname) + ) + ); + + $id = $this->arg('id'); + $aargs = array('format' => 'atom'); + if (!empty($id)) { + $aargs['id'] = $id; + } + + $atom->addLink( + $this->getSelfUri('ApiTimelineMentions', $aargs), + array('rel' => 'self', 'type' => 'application/atom+xml') ); + + $atom->addEntryFromNotices($this->notices); + $this->raw($atom->getString()); + break; case 'json': $this->showJsonTimeline($this->notices); diff --git a/actions/apitimelinepublic.php b/actions/apitimelinepublic.php index 0fb0788e9..1ff0fd261 100644 --- a/actions/apitimelinepublic.php +++ b/actions/apitimelinepublic.php @@ -74,7 +74,7 @@ class ApiTimelinePublicAction extends ApiPrivateAuthAction parent::prepare($args); $this->notices = $this->getNotices(); - + if ($this->since) { throw new ServerException("since parameter is disabled for performance; use since_id", 403); } @@ -109,7 +109,7 @@ class ApiTimelinePublicAction extends ApiPrivateAuthAction $sitename = common_config('site', 'name'); $sitelogo = (common_config('site', 'logo')) ? common_config('site', 'logo') : Theme::path('logo.png'); $title = sprintf(_("%s public timeline"), $sitename); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $id = "tag:$taguribase:PublicTimeline"; $link = common_root_url(); $subtitle = sprintf(_("%s updates from everyone!"), $sitename); @@ -122,11 +122,28 @@ class ApiTimelinePublicAction extends ApiPrivateAuthAction $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $sitelogo); break; case 'atom': - $selfuri = common_root_url() . 'api/statuses/public_timeline.atom'; - $this->showAtomTimeline( - $this->notices, $title, $id, $link, - $subtitle, null, $selfuri, $sitelogo + + $atom = new AtomNoticeFeed(); + + $atom->setId($id); + $atom->setTitle($title); + $atom->setSubtitle($subtitle); + $atom->setLogo($sitelogo); + $atom->setUpdated('now'); + + $atom->addLink(common_local_url('public')); + + $atom->addLink( + $this->getSelfUri( + 'ApiTimelinePublic', array('format' => 'atom') + ), + array('rel' => 'self', 'type' => 'application/atom+xml') ); + + $atom->addEntryFromNotices($this->notices); + + $this->raw($atom->getString()); + break; case 'json': $this->showJsonTimeline($this->notices); diff --git a/actions/apitimelineretweetedtome.php b/actions/apitimelineretweetedtome.php index e47bc30b8..73e35c86b 100644 --- a/actions/apitimelineretweetedtome.php +++ b/actions/apitimelineretweetedtome.php @@ -109,7 +109,7 @@ class ApiTimelineRetweetedToMeAction extends ApiAuthAction $profile = $this->auth_user->getProfile(); $title = sprintf(_("Repeated to %s"), $this->auth_user->nickname); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $id = "tag:$taguribase:RepeatedToMe:" . $this->auth_user->id; $link = common_local_url('all', array('nickname' => $this->auth_user->nickname)); diff --git a/actions/apitimelineretweetsofme.php b/actions/apitimelineretweetsofme.php index e4b09e9bd..c77912fd0 100644 --- a/actions/apitimelineretweetsofme.php +++ b/actions/apitimelineretweetsofme.php @@ -99,6 +99,8 @@ class ApiTimelineRetweetsOfMeAction extends ApiAuthAction $strm = $this->auth_user->repeatsOfMe($offset, $limit, $this->since_id, $this->max_id); + common_debug(var_export($strm, true)); + switch ($this->format) { case 'xml': $this->showXmlTimeline($strm); @@ -110,12 +112,40 @@ class ApiTimelineRetweetsOfMeAction extends ApiAuthAction $profile = $this->auth_user->getProfile(); $title = sprintf(_("Repeats of %s"), $this->auth_user->nickname); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $id = "tag:$taguribase:RepeatsOfMe:" . $this->auth_user->id; - $link = common_local_url('showstream', - array('nickname' => $this->auth_user->nickname)); - $this->showAtomTimeline($strm, $title, $id, $link); + header('Content-Type: application/atom+xml; charset=utf-8'); + + $atom = new AtomNoticeFeed(); + + $atom->setId($id); + $atom->setTitle($title); + $atom->setSubtitle($subtitle); + $atom->setUpdated('now'); + + $atom->addLink( + common_local_url( + 'showstream', + array('nickname' => $this->auth_user->nickname) + ) + ); + + $id = $this->arg('id'); + $aargs = array('format' => 'atom'); + if (!empty($id)) { + $aargs['id'] = $id; + } + + $atom->addLink( + $this->getSelfUri('ApiTimelineRetweetsOfMe', $aargs), + array('rel' => 'self', 'type' => 'application/atom+xml') + ); + + $atom->addEntryFromNotices($strm); + + $this->raw($atom->getString()); + break; default: diff --git a/actions/apitimelinetag.php b/actions/apitimelinetag.php index 1427d23b6..a29061fcc 100644 --- a/actions/apitimelinetag.php +++ b/actions/apitimelinetag.php @@ -100,16 +100,12 @@ class ApiTimelineTagAction extends ApiPrivateAuthAction $sitename = common_config('site', 'name'); $sitelogo = (common_config('site', 'logo')) ? common_config('site', 'logo') : Theme::path('logo.png'); $title = sprintf(_("Notices tagged with %s"), $this->tag); - $link = common_local_url( - 'tag', - array('tag' => $this->tag) - ); $subtitle = sprintf( _('Updates tagged with %1$s on %2$s!'), $this->tag, $sitename ); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $id = "tag:$taguribase:TagTimeline:".$tag; switch($this->format) { @@ -117,23 +113,52 @@ class ApiTimelineTagAction extends ApiPrivateAuthAction $this->showXmlTimeline($this->notices); break; case 'rss': - $this->showRssTimeline($this->notices, $title, $link, $subtitle, null, $sitelogo); - break; - case 'atom': - $selfuri = common_root_url() . - 'api/statusnet/tags/timeline/' . - $this->tag . '.atom'; - $this->showAtomTimeline( + $link = common_local_url( + 'tag', + array('tag' => $this->tag) + ); + $this->showRssTimeline( $this->notices, $title, - $id, $link, $subtitle, null, - $selfuri, $sitelogo ); break; + case 'atom': + + header('Content-Type: application/atom+xml; charset=utf-8'); + + $atom = new AtomNoticeFeed(); + + $atom->setId($id); + $atom->setTitle($title); + $atom->setSubtitle($subtitle); + $atom->setLogo($logo); + $atom->setUpdated('now'); + + $atom->addLink( + common_local_url( + 'tag', + array('tag' => $this->tag) + ) + ); + + $aargs = array('format' => 'atom'); + if (!empty($this->tag)) { + $aargs['tag'] = $this->tag; + } + + $atom->addLink( + $this->getSelfUri('ApiTimelineTag', $aargs), + array('rel' => 'self', 'type' => 'application/atom+xml') + ); + + $atom->addEntryFromNotices($this->notices); + $this->raw($atom->getString()); + + break; case 'json': $this->showJsonTimeline($this->notices); break; diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php index 830b16941..3e849cc78 100644 --- a/actions/apitimelineuser.php +++ b/actions/apitimelineuser.php @@ -116,7 +116,7 @@ class ApiTimelineUserAction extends ApiBareAuthAction $sitename = common_config('site', 'name'); $title = sprintf(_("%s timeline"), $this->user->nickname); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $id = "tag:$taguribase:UserTimeline:" . $this->user->id; $link = common_local_url( 'showstream', @@ -145,18 +145,60 @@ class ApiTimelineUserAction extends ApiBareAuthAction ); break; case 'atom': - if (isset($apidata['api_arg'])) { - $selfuri = common_root_url() . - 'api/statuses/user_timeline/' . - $apidata['api_arg'] . '.atom'; + + header('Content-Type: application/atom+xml; charset=utf-8'); + + // If this was called using an integer ID, i.e.: using the canonical + // URL for this user's feed, then pass the User object into the feed, + // so the OStatus plugin, and possibly other plugins, can access it. + // Feels sorta hacky. -- Z + + $atom = null; + $id = $this->arg('id'); + + if (strval(intval($id)) === strval($id)) { + $atom = new AtomUserNoticeFeed($this->user); } else { - $selfuri = common_root_url() . - 'api/statuses/user_timeline.atom'; + $atom = new AtomUserNoticeFeed(); + } + + $atom->setId($id); + $atom->setTitle($title); + $atom->setSubtitle($subtitle); + $atom->setLogo($logo); + $atom->setUpdated('now'); + + $atom->addLink( + common_local_url( + 'showstream', + array('nickname' => $this->user->nickname) + ) + ); + + $id = $this->arg('id'); + $aargs = array('format' => 'atom'); + if (!empty($id)) { + $aargs['id'] = $id; } - $this->showAtomTimeline( - $this->notices, $title, $id, $link, - $subtitle, $suplink, $selfuri, $logo + + $atom->addLink( + $this->getSelfUri('ApiTimelineUser', $aargs), + array('rel' => 'self', 'type' => 'application/atom+xml') + ); + + $atom->addLink( + $suplink, + array( + 'rel' => 'http://api.friendfeed.com/2008/03#sup', + 'type' => 'application/json' + ) ); + + $atom->addEntryFromNotices($this->notices); + + #$this->raw($atom->getString()); + print $atom->getString(); // temporary for output buffering + break; case 'json': $this->showJsonTimeline($this->notices); diff --git a/actions/doc.php b/actions/doc.php index eaf4b7df2..459f5f096 100644 --- a/actions/doc.php +++ b/actions/doc.php @@ -173,6 +173,10 @@ class DocAction extends Action } $local = glob(INSTALLDIR.'/local/doc-src/'.$this->title.'.*'); + if ($local === false) { + // Some systems return false, others array(), if dir didn't exist. + $local = array(); + } if (count($local) || isset($localDef)) { return $this->negotiateLanguage($local, $localDef); @@ -183,6 +187,9 @@ class DocAction extends Action } $dist = glob(INSTALLDIR.'/doc-src/'.$this->title.'.*'); + if ($dist === false) { + $dist = array(); + } if (count($dist) || isset($distDef)) { return $this->negotiateLanguage($dist, $distDef); diff --git a/actions/favor.php b/actions/favor.php index 2aeb1da61..afca9768a 100644 --- a/actions/favor.php +++ b/actions/favor.php @@ -79,7 +79,7 @@ class FavorAction extends Action $this->clientError(_('This notice is already a favorite!')); return; } - $fave = Fave::addNew($user, $notice); + $fave = Fave::addNew($user->getProfile(), $notice); if (!$fave) { $this->serverError(_('Could not create favorite.')); return; diff --git a/actions/groupmembers.php b/actions/groupmembers.php index 0f47c268d..f16e972a4 100644 --- a/actions/groupmembers.php +++ b/actions/groupmembers.php @@ -192,7 +192,9 @@ class GroupMemberListItem extends ProfileListItem { $user = common_current_user(); - if (!empty($user) && $user->id != $this->profile->id && $user->isAdmin($this->group) && + if (!empty($user) && + $user->id != $this->profile->id && + ($user->isAdmin($this->group) || $user->hasRight(Right::MAKEGROUPADMIN)) && !$this->profile->isAdmin($this->group)) { $this->out->elementStart('li', 'entity_make_admin'); $maf = new MakeAdminForm($this->out, $this->profile, $this->group, diff --git a/actions/makeadmin.php b/actions/makeadmin.php index 9ad7d6e7c..f19348648 100644 --- a/actions/makeadmin.php +++ b/actions/makeadmin.php @@ -87,7 +87,8 @@ class MakeadminAction extends Action return false; } $user = common_current_user(); - if (!$user->isAdmin($this->group)) { + if (!$user->isAdmin($this->group) && + !$user->hasRight(Right::MAKEGROUPADMIN)) { $this->clientError(_('Only an admin can make another user an admin.'), 401); return false; } diff --git a/actions/public.php b/actions/public.php index 982dfde15..50278bfce 100644 --- a/actions/public.php +++ b/actions/public.php @@ -131,12 +131,20 @@ class PublicAction extends Action return _('Public timeline'); } } - + function extraHead() { parent::extraHead(); $this->element('meta', array('http-equiv' => 'X-XRDS-Location', 'content' => common_local_url('publicxrds'))); + + $rsd = common_local_url('rsd'); + + // RSD, http://tales.phrasewise.com/rfc/rsd + + $this->element('link', array('rel' => 'EditURI', + 'type' => 'application/rsd+xml', + 'href' => $rsd)); } /** diff --git a/actions/rsd.php b/actions/rsd.php new file mode 100644 index 000000000..f88bf2e9a --- /dev/null +++ b/actions/rsd.php @@ -0,0 +1,226 @@ +<?php +/** + * StatusNet - the distributed open-source microblogging tool + * Copyright (C) 2008-2010, StatusNet, Inc. + * + * Really Simple Discovery (RSD) for API access + * + * PHP version 5 + * + * 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> + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * RSD action class + * + * Really Simple Discovery (RSD) is a simple (to a fault, maybe) + * discovery tool for blog APIs. + * + * http://tales.phrasewise.com/rfc/rsd + * + * Anil Dash suggested that RSD be used for services that implement + * the Twitter API: + * + * http://dashes.com/anil/2009/12/the-twitter-api-is-finished.html + * + * It's in use now for WordPress.com blogs: + * + * http://matt.wordpress.com/xmlrpc.php?rsd + * + * I (evan@status.net) have tried to stay faithful to the premise of + * RSD, while adding information useful to StatusNet client developers. + * In particular: + * + * - There is a link from each user's profile page to their personal + * RSD feed. A personal rsd.xml includes a 'blogID' element that is + * their username. + * - There is a link from the public root to '/rsd.xml', a public RSD + * feed. It's identical to the personal rsd except it doesn't include + * a blogId. + * - I've added a setting to the API to indicate that OAuth support is + * available. + * + * @category API + * @package StatusNet + * @author Evan Prodromou <evan@status.net> + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + +class RsdAction extends Action +{ + /** + * Optional attribute for the personal rsd.xml file. + */ + + var $user = null; + + /** + * Prepare the action for use. + * + * Check for a nickname; redirect if non-canonical; if + * not provided, assume public rsd.xml. + * + * @param array $args GET, POST, and URI arguments. + * + * @return boolean success flag + */ + + function prepare($args) + { + parent::prepare($args); + + // optional argument + + $nickname_arg = $this->arg('nickname'); + + if (empty($nickname_arg)) { + $this->user = null; + } else { + $nickname = common_canonical_nickname($nickname_arg); + + // Permanent redirect on non-canonical nickname + + if ($nickname_arg != $nickname) { + common_redirect(common_local_url('rsd', + array('nickname' => $nickname)), + 301); + return false; + } + + $this->user = User::staticGet('nickname', $nickname); + + if (empty($this->user)) { + $this->clientError(_('No such user.'), 404); + return false; + } + } + + return true; + } + + /** + * Action handler. + * + * Outputs the XML format for an RSD file. May include + * personal information if this is a personal file + * (based on whether $user attribute is set). + * + * @param array $args array of arguments + * + * @return nothing + */ + + function handle($args) + { + header('Content-Type: application/rsd+xml'); + + $this->startXML(); + + $rsdNS = 'http://archipelago.phrasewise.com/rsd'; + $this->elementStart('rsd', array('version' => '1.0', + 'xmlns' => $rsdNS)); + $this->elementStart('service'); + $this->element('engineName', null, _('StatusNet')); + $this->element('engineLink', null, 'http://status.net/'); + $this->elementStart('apis'); + if (Event::handle('StartRsdListApis', array($this, $this->user))) { + + $blogID = (empty($this->user)) ? '' : $this->user->nickname; + $apiAttrs = array('name' => 'Twitter', + 'preferred' => 'true', + 'apiLink' => $this->_apiRoot(), + 'blogID' => $blogID); + + $this->elementStart('api', $apiAttrs); + $this->elementStart('settings'); + $this->element('docs', null, + 'http://status.net/wiki/TwitterCompatibleAPI'); + $this->element('setting', array('name' => 'OAuth'), + 'true'); + $this->elementEnd('settings'); + $this->elementEnd('api'); + Event::handle('EndRsdListApis', array($this, $this->user)); + } + $this->elementEnd('apis'); + $this->elementEnd('service'); + $this->elementEnd('rsd'); + + $this->endXML(); + + return true; + } + + /** + * Returns last-modified date for use in caching + * + * Per-user rsd.xml is dated to last change of user + * (in case of nickname change); public has no date. + * + * @return string date of last change of this page + */ + + function lastModified() + { + if (!empty($this->user)) { + return $this->user->modified; + } else { + return null; + } + } + + /** + * Flag to indicate if this action is read-only + * + * It is; it doesn't change the DB. + * + * @param array $args ignored + * + * @return boolean true + */ + + function isReadOnly($args) + { + return true; + } + + /** + * Return current site's API root + * + * Varies based on URL parameters, like if fancy URLs are + * turned on. + * + * @return string API root URI for this site + */ + + private function _apiRoot() + { + if (common_config('site', 'fancy')) { + return common_path('api/', true); + } else { + return common_path('index.php/api/', true); + } + } +} diff --git a/actions/showgroup.php b/actions/showgroup.php index 8042a4951..eb1238902 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -330,13 +330,13 @@ class ShowgroupAction extends GroupDesignAction new Feed(Feed::RSS2, common_local_url('ApiTimelineGroup', array('format' => 'rss', - 'id' => $this->group->nickname)), + 'id' => $this->group->id)), sprintf(_('Notice feed for %s group (RSS 2.0)'), $this->group->nickname)), new Feed(Feed::ATOM, common_local_url('ApiTimelineGroup', array('format' => 'atom', - 'id' => $this->group->nickname)), + 'id' => $this->group->id)), sprintf(_('Notice feed for %s group (Atom)'), $this->group->nickname)), new Feed(Feed::FOAF, diff --git a/actions/showstream.php b/actions/showstream.php index c52919386..f9407e35a 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -131,14 +131,14 @@ class ShowstreamAction extends ProfileAction new Feed(Feed::RSS2, common_local_url('ApiTimelineUser', array( - 'id' => $this->user->nickname, + 'id' => $this->user->id, 'format' => 'rss')), sprintf(_('Notice feed for %s (RSS 2.0)'), $this->user->nickname)), new Feed(Feed::ATOM, common_local_url('ApiTimelineUser', array( - 'id' => $this->user->nickname, + 'id' => $this->user->id, 'format' => 'atom')), sprintf(_('Notice feed for %s (Atom)'), $this->user->nickname)), @@ -178,6 +178,15 @@ class ShowstreamAction extends ProfileAction $this->element('link', array('rel' => 'microsummary', 'href' => common_local_url('microsummary', array('nickname' => $this->profile->nickname)))); + + $rsd = common_local_url('rsd', + array('nickname' => $this->profile->nickname)); + + // RSD, http://tales.phrasewise.com/rfc/rsd + $this->element('link', array('rel' => 'EditURI', + 'type' => 'application/rsd+xml', + 'href' => $rsd)); + } function showProfile() diff --git a/actions/twitapisearchatom.php b/actions/twitapisearchatom.php index baed2a0c7..e389ddec8 100644 --- a/actions/twitapisearchatom.php +++ b/actions/twitapisearchatom.php @@ -245,7 +245,7 @@ class TwitapisearchatomAction extends ApiAction 'xmlns:twitter' => 'http://api.twitter.com/', 'xml:lang' => 'en-US')); // XXX Other locales ? - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $this->element('id', null, "tag:$taguribase:search/$server"); $site_uri = common_path(false); @@ -329,7 +329,7 @@ class TwitapisearchatomAction extends ApiAction $this->elementStart('entry'); - $taguribase = common_config('integration', 'taguri'); + $taguribase = TagURI::base(); $this->element('id', null, "tag:$taguribase:$notice->id"); $this->element('published', null, common_date_w3dtf($notice->created)); diff --git a/actions/userauthorization.php b/actions/userauthorization.php index 4321f1302..7f71c60db 100644 --- a/actions/userauthorization.php +++ b/actions/userauthorization.php @@ -127,10 +127,10 @@ class UserauthorizationAction extends Action $location = $params->getLocation(); $avatar = $params->getAvatarURL(); - $this->elementStart('div', array('class' => 'profile')); $this->elementStart('div', 'entity_profile vcard'); - $this->elementStart('a', array('href' => $profile, - 'class' => 'url')); + $this->elementStart('dl', 'entity_depiction'); + $this->element('dt', null, _('Photo')); + $this->elementStart('dd'); if ($avatar) { $this->element('img', array('src' => $avatar, 'class' => 'photo avatar', @@ -138,11 +138,19 @@ class UserauthorizationAction extends Action 'height' => AVATAR_PROFILE_SIZE, 'alt' => $nickname)); } + $this->elementEnd('dd'); + $this->elementEnd('dl'); + + $this->elementStart('dl', 'entity_nickname'); + $this->element('dt', null, _('Nickname')); + $this->elementStart('dd'); $hasFN = ($fullname !== '') ? 'nickname' : 'fn nickname'; - $this->elementStart('span', $hasFN); + $this->elementStart('a', array('href' => $profile, + 'class' => 'url '.$hasFN)); $this->raw($nickname); - $this->elementEnd('span'); $this->elementEnd('a'); + $this->elementEnd('dd'); + $this->elementEnd('dl'); if (!is_null($fullname)) { $this->elementStart('dl', 'entity_fn'); @@ -214,7 +222,6 @@ class UserauthorizationAction extends Action $this->elementEnd('li'); $this->elementEnd('ul'); $this->elementEnd('div'); - $this->elementEnd('div'); } function sendAuthorization() @@ -350,4 +357,4 @@ class UserauthorizationAction extends Action } } } -}
\ No newline at end of file +} |