summaryrefslogtreecommitdiff
path: root/actions
diff options
context:
space:
mode:
Diffstat (limited to 'actions')
-rw-r--r--actions/allrss.php1
-rw-r--r--actions/api.php305
-rw-r--r--actions/apiaccountratelimitstatus.php112
-rw-r--r--actions/apiaccountverifycredentials.php85
-rw-r--r--actions/apiblockcreate.php114
-rw-r--r--actions/apiblockdestroy.php113
-rw-r--r--actions/apidirectmessage.php375
-rw-r--r--actions/apidirectmessagenew.php188
-rw-r--r--actions/apifavoritecreate.php168
-rw-r--r--actions/apifavoritedestroy.php150
-rw-r--r--actions/apifriendshipscreate.php137
-rw-r--r--actions/apifriendshipsdestroy.php139
-rw-r--r--actions/apifriendshipsexists.php128
-rw-r--r--actions/apifriendshipsshow.php168
-rw-r--r--actions/apigroupcreate.php381
-rw-r--r--actions/apigroupismember.php122
-rw-r--r--actions/apigroupjoin.php163
-rw-r--r--actions/apigroupleave.php149
-rw-r--r--actions/apigrouplist.php223
-rw-r--r--actions/apigrouplistall.php208
-rw-r--r--actions/apigroupmembership.php192
-rw-r--r--actions/apigroupshow.php152
-rw-r--r--actions/apihelptest.php96
-rw-r--r--actions/apistatusesdestroy.php154
-rw-r--r--actions/apistatusesshow.php206
-rw-r--r--actions/apistatusesupdate.php241
-rw-r--r--actions/apistatusnetconfig.php142
-rw-r--r--actions/apistatusnetversion.php102
-rw-r--r--actions/apisubscriptions.php266
-rw-r--r--actions/apitimelinefavorites.php237
-rw-r--r--actions/apitimelinefriends.php247
-rw-r--r--actions/apitimelinegroup.php231
-rw-r--r--actions/apitimelinementions.php233
-rw-r--r--actions/apitimelinepublic.php213
-rw-r--r--actions/apitimelinetag.php224
-rw-r--r--actions/apitimelineuser.php248
-rw-r--r--actions/apiuserfollowers.php89
-rw-r--r--actions/apiuserfriends.php89
-rw-r--r--actions/apiusershow.php126
-rw-r--r--actions/avatarsettings.php8
-rw-r--r--actions/deletenotice.php38
-rw-r--r--actions/editgroup.php1
-rw-r--r--actions/favoritesrss.php11
-rw-r--r--actions/finishremotesubscribe.php63
-rw-r--r--actions/foafgroup.php173
-rw-r--r--actions/grouprss.php1
-rw-r--r--actions/groupsearch.php2
-rw-r--r--actions/newnotice.php10
-rw-r--r--actions/publicrss.php18
-rw-r--r--actions/repliesrss.php1
-rw-r--r--actions/showgroup.php7
-rw-r--r--actions/showstream.php7
-rw-r--r--actions/twitapiaccount.php127
-rw-r--r--actions/twitapiblocks.php74
-rw-r--r--actions/twitapidirect_messages.php305
-rw-r--r--actions/twitapifavorites.php216
-rw-r--r--actions/twitapifriendships.php250
-rw-r--r--actions/twitapigroups.php329
-rw-r--r--actions/twitapihelp.php57
-rw-r--r--actions/twitapinotifications.php40
-rw-r--r--actions/twitapisearchatom.php8
-rw-r--r--actions/twitapisearchjson.php10
-rw-r--r--actions/twitapistatuses.php606
-rw-r--r--actions/twitapistatusnet.php175
-rw-r--r--actions/twitapitags.php113
-rw-r--r--actions/twitapitrends.php6
-rw-r--r--actions/twitapiusers.php80
-rw-r--r--actions/updateprofile.php49
-rw-r--r--actions/userrss.php5
69 files changed, 6884 insertions, 2823 deletions
diff --git a/actions/allrss.php b/actions/allrss.php
index 57efb73f0..28b1be27d 100644
--- a/actions/allrss.php
+++ b/actions/allrss.php
@@ -68,6 +68,7 @@ class AllrssAction extends Rss10Action
$this->clientError(_('No such user.'));
return false;
} else {
+ $this->notices = $this->getNotices($this->limit);
return true;
}
}
diff --git a/actions/api.php b/actions/api.php
deleted file mode 100644
index d570bb017..000000000
--- a/actions/api.php
+++ /dev/null
@@ -1,305 +0,0 @@
-<?php
-/**
- * StatusNet - the 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/>.
- *
- * @category Actions
- * @package Actions
- * @author Evan Prodromou <evan@status.net>
- * @author Brenda Wallace <shiny@cpan.org>
- * @author Jeffery To <jeffery.to@gmail.com>
- * @author Robin Millette <millette@controlyourself.ca>
- * @author Tom Adams <tom@holizz.com>
- * @author Christopher Vollick <psycotica0@gmail.com>
- * @author CiaranG <ciaran@ciarang.com>
- * @author Craig Andrews <candrews@integralblue.com>
- * @author Gina Haeussge <osd@foosel.net>
- * @author Mike Cochrane <mikec@mikenz.geek.nz>
- * @author Sarven Capadisli <csarven@status.net>
- * @license GNU Affero General Public License http://www.gnu.org/licenses/
- * @link http://status.net
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-class ApiAction extends Action
-{
-
- var $user;
- var $content_type;
- var $api_arg;
- var $api_method;
- var $api_action;
- var $auth_user;
- var $auth_pw;
-
- function handle($args)
- {
- parent::handle($args);
-
- $this->api_action = $this->arg('apiaction');
- $method = $this->arg('method');
- $argument = $this->arg('argument');
- $this->basic_auth_process_header();
-
- if (isset($argument)) {
- $cmdext = explode('.', $argument);
- $this->api_arg = $cmdext[0];
- $this->api_method = $method;
- $this->content_type = strtolower($cmdext[1]);
- } else {
-
- //Requested format / content-type will be an extension on the method
- $cmdext = explode('.', $method);
- $this->api_method = $cmdext[0];
- $this->content_type = strtolower($cmdext[1]);
- }
-
- if ($this->requires_auth()) {
- if (!isset($this->auth_user)) {
-
- //This header makes basic auth go
- header('WWW-Authenticate: Basic realm="StatusNet API"');
-
- //If the user hits cancel -- bam!
- $this->show_basic_auth_error();
- } else {
- $nickname = $this->auth_user;
- $password = $this->auth_pw;
- $user = common_check_user($nickname, $password);
-
- if ($user) {
- $this->user = $user;
- $this->process_command();
- } else {
- //basic authentication failed
- list($proxy, $ip) = common_client_ip();
-
- common_log(LOG_WARNING, "Failed API auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip.");
- $this->show_basic_auth_error();
- }
- }
- } else {
-
- // Caller might give us a username even if not required
- if (isset($this->auth_user)) {
- $user = User::staticGet('nickname', $this->auth_user);
- if ($user) {
- $this->user = $user;
- }
- //Twitter doesn't throw an error if the user isn't found
- }
-
- $this->process_command();
- }
- }
-
- function process_command()
- {
- $action = "twitapi$this->api_action";
- $actionfile = INSTALLDIR."/actions/$action.php";
-
- if (file_exists($actionfile)) {
- include_once $actionfile;
- $action_class = ucfirst($action)."Action";
- $action_obj = new $action_class();
-
- if (!$action_obj->prepare($this->args)) {
- return;
- }
-
- if (method_exists($action_obj, $this->api_method)) {
- $apidata = array( 'content-type' => $this->content_type,
- 'api_method' => $this->api_method,
- 'api_arg' => $this->api_arg,
- 'user' => $this->user);
-
- call_user_func(array($action_obj, $this->api_method), $_REQUEST, $apidata);
- } else {
- $this->clientError("API method not found!", $code = 404);
- }
- } else {
- $this->clientError("API method not found!", $code = 404);
- }
- }
-
- // Whitelist of API methods that don't need authentication
- function requires_auth()
- {
- static $noauth = array( 'statuses/public_timeline',
- 'statuses/show',
- 'users/show',
- 'help/test',
- 'help/downtime_schedule',
- 'statusnet/version',
- 'statusnet/config',
- 'statusnet/wadl',
- 'tags/timeline',
- 'oembed/oembed',
- 'groups/show',
- 'groups/timeline',
- 'groups/list_all',
- 'groups/membership',
- 'groups/is_member',
- 'groups/timeline');
-
- static $bareauth = array('statuses/user_timeline',
- 'statuses/friends_timeline',
- 'statuses/friends',
- 'statuses/replies',
- 'statuses/mentions',
- 'statuses/followers',
- 'favorites/favorites',
- 'friendships/show',
- 'groups/list_groups');
-
- $fullname = "$this->api_action/$this->api_method";
-
- // If the site is "private", all API methods except statusnet/config
- // need authentication
-
- if (common_config('site', 'private')) {
- return $fullname != 'statusnet/config' || false;
- }
-
- // bareauth: only needs auth if without an argument or query param specifying user
-
- if (in_array($fullname, $bareauth)) {
-
- // Special case: friendships/show only needs auth if source_id or
- // source_screen_name is not specified as a param
-
- if ($fullname == 'friendships/show') {
-
- $source_id = $this->arg('source_id');
- $source_screen_name = $this->arg('source_screen_name');
-
- if (empty($source_id) && empty($source_screen_name)) {
- return true;
- }
-
- return false;
- }
-
- // if all of these are empty, auth is required
-
- $id = $this->arg('id');
- $user_id = $this->arg('user_id');
- $screen_name = $this->arg('screen_name');
-
- if (empty($this->api_arg)
- && empty($id)
- && empty($user_id)
- && empty($screen_name)
- ) {
- return true;
- } else {
- return false;
- }
-
- } else if (in_array($fullname, $noauth)) {
-
- // noauth: never needs auth
-
- return false;
- } else {
-
- // everybody else needs auth
-
- return true;
- }
- }
-
- function basic_auth_process_header()
- {
- if (isset($_SERVER['AUTHORIZATION']) || isset($_SERVER['HTTP_AUTHORIZATION'])) {
- $authorization_header = isset($_SERVER['HTTP_AUTHORIZATION'])? $_SERVER['HTTP_AUTHORIZATION'] : $_SERVER['AUTHORIZATION'];
- }
-
- if (isset($_SERVER['PHP_AUTH_USER'])) {
- $this->auth_user = $_SERVER['PHP_AUTH_USER'];
- $this->auth_pw = $_SERVER['PHP_AUTH_PW'];
- } elseif (isset($authorization_header) && strstr(substr($authorization_header, 0, 5), 'Basic')) {
- // decode the HTTP_AUTHORIZATION header on php-cgi server self
- // on fcgid server the header name is AUTHORIZATION
-
- $auth_hash = base64_decode(substr($authorization_header, 6));
- list($this->auth_user, $this->auth_pw) = explode(':', $auth_hash);
-
- // set all to null on a empty basic auth request
- if ($this->auth_user == "") {
- $this->auth_user = null;
- $this->auth_pw = null;
- }
- } else {
- $this->auth_user = null;
- $this->auth_pw = null;
- }
- }
-
- function show_basic_auth_error()
- {
- header('HTTP/1.1 401 Unauthorized');
- $msg = 'Could not authenticate you.';
-
- if ($this->content_type == 'xml') {
- header('Content-Type: application/xml; charset=utf-8');
- $this->startXML();
- $this->elementStart('hash');
- $this->element('error', null, $msg);
- $this->element('request', null, $_SERVER['REQUEST_URI']);
- $this->elementEnd('hash');
- $this->endXML();
- } else if ($this->content_type == 'json') {
- header('Content-Type: application/json; charset=utf-8');
- $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']);
- print(json_encode($error_array));
- } else {
- header('Content-type: text/plain');
- print "$msg\n";
- }
- }
-
- function isReadOnly($args)
- {
- $apiaction = $args['apiaction'];
- $method = $args['method'];
-
- list($cmdtext, $fmt) = explode('.', $method);
-
- static $write_methods = array(
- 'account' => array('update_location', 'update_delivery_device', 'end_session'),
- 'blocks' => array('create', 'destroy'),
- 'direct_messages' => array('create', 'destroy'),
- 'favorites' => array('create', 'destroy'),
- 'friendships' => array('create', 'destroy'),
- 'help' => array(),
- 'notifications' => array('follow', 'leave'),
- 'statuses' => array('update', 'destroy'),
- 'users' => array()
- );
-
- if (array_key_exists($apiaction, $write_methods)) {
- if (!in_array($cmdtext, $write_methods[$apiaction])) {
- return true;
- }
- }
-
- return false;
- }
-}
diff --git a/actions/apiaccountratelimitstatus.php b/actions/apiaccountratelimitstatus.php
new file mode 100644
index 000000000..96179f175
--- /dev/null
+++ b/actions/apiaccountratelimitstatus.php
@@ -0,0 +1,112 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Dummy action that emulates Twitter's rate limit status API resource
+ *
+ * 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>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apibareauth.php';
+
+/**
+ * We don't have a rate limit, but some clients check this method.
+ * It always returns the same thing: 150 hits left.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiAccountRateLimitStatusAction extends ApiBareAuthAction
+{
+
+ /**
+ * Handle the request
+ *
+ * Return some Twitter-ish data about API limits
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (!in_array($this->format, array('xml', 'json'))) {
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ return;
+ }
+
+ $reset = new DateTime();
+ $reset->modify('+1 hour');
+
+ $this->initDocument($this->format);
+
+ if ($this->format == 'xml') {
+ $this->elementStart('hash');
+ $this->element('remaining-hits', array('type' => 'integer'), 150);
+ $this->element('hourly-limit', array('type' => 'integer'), 150);
+ $this->element(
+ 'reset-time', array('type' => 'datetime'),
+ common_date_iso8601($reset->format('r'))
+ );
+ $this->element(
+ 'reset_time_in_seconds',
+ array('type' => 'integer'),
+ strtotime('+1 hour')
+ );
+ $this->elementEnd('hash');
+ } elseif ($this->format == 'json') {
+ $out = array(
+ 'reset_time_in_seconds' => strtotime('+1 hour'),
+ 'remaining_hits' => 150,
+ 'hourly_limit' => 150,
+ 'reset_time' => common_date_rfc2822(
+ $reset->format('r')
+ )
+ );
+ print json_encode($out);
+ }
+
+ $this->endDocument($this->format);
+ }
+
+}
+
diff --git a/actions/apiaccountverifycredentials.php b/actions/apiaccountverifycredentials.php
new file mode 100644
index 000000000..08b201dbf
--- /dev/null
+++ b/actions/apiaccountverifycredentials.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Test if supplied user credentials are valid.
+ *
+ * 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>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Check a user's credentials. Returns an HTTP 200 OK response code and a
+ * representation of the requesting user if authentication was successful;
+ * returns a 401 status code and an error message if not.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiAccountVerifyCredentialsAction extends ApiAuthAction
+{
+
+ /**
+ * Handle the request
+ *
+ * Check whether the credentials are valid and output the result
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ switch ($this->format) {
+ case 'xml':
+ case 'json':
+ $args['id'] = $this->auth_user->id;
+ $action_obj = new ApiUserShowAction();
+ if ($action_obj->prepare($args)) {
+ $action_obj->handle($args);
+ }
+ break;
+ default:
+ header('Content-Type: text/html; charset=utf-8');
+ print 'Authorized';
+ }
+
+ }
+
+}
diff --git a/actions/apiblockcreate.php b/actions/apiblockcreate.php
new file mode 100644
index 000000000..1cab2df5d
--- /dev/null
+++ b/actions/apiblockcreate.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Block a user via the API
+ *
+ * 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>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Blocks the user specified in the ID parameter as the authenticating user.
+ * Destroys a friendship to the blocked user if it exists. Returns the
+ * blocked user in the requested format when successful.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiBlockCreateAction extends ApiAuthAction
+{
+ var $other = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+ $this->other = $this->getTargetUser($this->arg('id'));
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Save the new message
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(
+ _('This method requires a POST.'),
+ 400,
+ $this->format
+ );
+ return;
+ }
+
+ if (empty($this->user) || empty($this->other)) {
+ $this->clientError(_('No such user!'), 404, $this->format);
+ return;
+ }
+
+ if ($this->user->hasBlocked($this->other)
+ || $this->user->block($this->other)
+ ) {
+ $this->initDocument($this->format);
+ $this->showProfile($this->other, $this->format);
+ $this->endDocument($this->format);
+ } else {
+ $this->serverError(_('Block user failed.'), 500, $this->format);
+ }
+
+ }
+
+}
+
diff --git a/actions/apiblockdestroy.php b/actions/apiblockdestroy.php
new file mode 100644
index 000000000..16dbf94ca
--- /dev/null
+++ b/actions/apiblockdestroy.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Un-block a user via the API
+ *
+ * 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>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Un-blocks the user specified in the ID parameter for the authenticating user.
+ * Returns the un-blocked user in the requested format when successful.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiBlockDestroyAction extends ApiAuthAction
+{
+ var $other = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+ $this->other = $this->getTargetUser($this->arg('id'));
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Save the new message
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(
+ _('This method requires a POST.'),
+ 400,
+ $this->format
+ );
+ return;
+ }
+
+ if (empty($this->user) || empty($this->other)) {
+ $this->clientError(_('No such user!'), 404, $this->format);
+ return;
+ }
+
+ if (!$this->user->hasBlocked($this->other)
+ || $this->user->unblock($this->other)
+ ) {
+ $this->initDocument($this->format);
+ $this->showProfile($this->other, $this->format);
+ $this->endDocument($this->format);
+ } else {
+ $this->serverError(_('Unblock user failed.'));
+ }
+
+ }
+
+}
+
diff --git a/actions/apidirectmessage.php b/actions/apidirectmessage.php
new file mode 100644
index 000000000..a21fe86d2
--- /dev/null
+++ b/actions/apidirectmessage.php
@@ -0,0 +1,375 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a the direct messages from or to 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 Adrian Lang <mail@adrianlang.de>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Show a list of direct messages from or to the authenticating user
+ *
+ * @category API
+ * @package StatusNet
+ * @author Adrian Lang <mail@adrianlang.de>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiDirectMessageAction extends ApiAuthAction
+{
+ var $messages = null;
+ var $title = null;
+ var $subtitle = null;
+ var $link = null;
+ var $selfuri_base = null;
+ var $id = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user!'), 404, $this->format);
+ return;
+ }
+
+ $server = common_root_url();
+ $taguribase = common_config('integration', 'taguri');
+
+ if ($this->arg('sent')) {
+
+ // Action was called by /api/direct_messages/sent.format
+
+ $this->title = sprintf(
+ _("Direct messages from %s"),
+ $this->user->nickname
+ );
+ $this->subtitle = sprintf(
+ _("All the direct messages sent from %s"),
+ $this->user->nickname
+ );
+ $this->link = $server . $this->user->nickname . '/outbox';
+ $this->selfuri_base = common_root_url() . 'api/direct_messages/sent';
+ $this->id = "tag:$taguribase:SentDirectMessages:" . $this->user->id;
+ } else {
+ $this->title = sprintf(
+ _("Direct messages to %s"),
+ $this->user->nickname
+ );
+ $this->subtitle = sprintf(
+ _("All the direct messages sent to %s"),
+ $this->user->nickname
+ );
+ $this->link = $server . $this->user->nickname . '/inbox';
+ $this->selfuri_base = common_root_url() . 'api/direct_messages';
+ $this->id = "tag:$taguribase:DirectMessages:" . $this->user->id;
+ }
+
+ $this->messages = $this->getMessages();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Show the messages
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showMessages();
+ }
+
+ /**
+ * Show the messages
+ *
+ * @return void
+ */
+
+ function showMessages()
+ {
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlDirectMessages();
+ break;
+ case 'rss':
+ $this->showRssDirectMessages();
+ break;
+ case 'atom':
+ $this->showAtomDirectMessages();
+ break;
+ case 'json':
+ $this->showJsonDirectMessages();
+ break;
+ default:
+ $this->clientError(_('API method not found!'), $code = 404);
+ break;
+ }
+ }
+
+ /**
+ * Get notices
+ *
+ * @return array notices
+ */
+
+ function getMessages()
+ {
+ $message = new Message();
+
+ if ($this->arg('sent')) {
+ $message->from_profile = $this->user->id;
+ } else {
+ $message->to_profile = $this->user->id;
+ }
+
+ if (!empty($this->max_id)) {
+ $message->whereAdd('id <= ' . $this->max_id);
+ }
+
+ if (!empty($this->since_id)) {
+ $message->whereAdd('id > ' . $this->since_id);
+ }
+
+ if (!empty($since)) {
+ $d = date('Y-m-d H:i:s', $this->since);
+ $message->whereAdd("created > '$d'");
+ }
+
+ $message->orderBy('created DESC, id DESC');
+ $message->limit((($this->page - 1) * $this->count), $this->count);
+ $message->find();
+
+ $messages = array();
+
+ while ($message->fetch()) {
+ $messages[] = clone($message);
+ }
+
+ return $messages;
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this notice last modified?
+ *
+ * @return string datestamp of the latest notice in the stream
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->messages)) {
+ return strtotime($this->messages[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * Shows a list of direct messages as Twitter-style XML array
+ *
+ * @return void
+ */
+
+ function showXmlDirectMessages()
+ {
+ $this->initDocument('xml');
+ $this->elementStart('direct-messages', array('type' => 'array'));
+
+ foreach ($this->messages as $m) {
+ $dm_array = $this->directMessageArray($m);
+ $this->showXmlDirectMessage($dm_array);
+ }
+
+ $this->elementEnd('direct-messages');
+ $this->endDocument('xml');
+ }
+
+ /**
+ * Shows a list of direct messages as a JSON encoded array
+ *
+ * @return void
+ */
+
+ function showJsonDirectMessages()
+ {
+ $this->initDocument('json');
+
+ $dmsgs = array();
+
+ foreach ($this->messages as $m) {
+ $dm_array = $this->directMessageArray($m);
+ array_push($dmsgs, $dm_array);
+ }
+
+ $this->showJsonObjects($dmsgs);
+ $this->endDocument('json');
+ }
+
+ /**
+ * Shows a list of direct messages as RSS items
+ *
+ * @return void
+ */
+
+ function showRssDirectMessages()
+ {
+ $this->initDocument('rss');
+
+ $this->element('title', null, $this->title);
+
+ $this->element('link', null, $this->link);
+ $this->element('description', null, $this->subtitle);
+ $this->element('language', null, 'en-us');
+
+ $this->element(
+ 'atom:link',
+ array(
+ 'type' => 'application/rss+xml',
+ 'href' => $this->selfuri_base . '.rss',
+ 'rel' => self
+ ),
+ null
+ );
+ $this->element('ttl', null, '40');
+
+ foreach ($this->messages as $m) {
+ $entry = $this->rssDirectMessageArray($m);
+ $this->showTwitterRssItem($entry);
+ }
+
+ $this->endTwitterRss();
+ }
+
+ /**
+ * Shows a list of direct messages as Atom entries
+ *
+ * @return void
+ */
+
+ function showAtomDirectMessages()
+ {
+ $this->initDocument('atom');
+
+ $this->element('title', null, $this->title);
+ $this->element('id', null, $this->id);
+
+ $selfuri = common_root_url() . 'api/direct_messages.atom';
+
+ $this->element(
+ 'link', array(
+ 'href' => $this->link,
+ 'rel' => 'alternate',
+ 'type' => 'text/html'),
+ null
+ );
+ $this->element(
+ 'link', array(
+ 'href' => $this->selfuri_base . '.atom', 'rel' => 'self',
+ 'type' => 'application/atom+xml'),
+ null
+ );
+ $this->element('updated', null, common_date_iso8601('now'));
+ $this->element('subtitle', null, $this->subtitle);
+
+ foreach ($this->messages as $m) {
+ $entry = $this->rssDirectMessageArray($m);
+ $this->showTwitterAtomEntry($entry);
+ }
+
+ $this->endDocument('atom');
+ }
+
+ /**
+ * An entity tag for this notice
+ *
+ * Returns an Etag based on the action name, language, and
+ * timestamps of the notice
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->messages)) {
+
+ $last = count($this->messages) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ strtotime($this->messages[0]->created),
+ strtotime($this->messages[$last]->created)
+ )
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apidirectmessagenew.php b/actions/apidirectmessagenew.php
new file mode 100644
index 000000000..fa6cafbe8
--- /dev/null
+++ b/actions/apidirectmessagenew.php
@@ -0,0 +1,188 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Send a direct message via the API
+ *
+ * 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 Adrian Lang <mail@adrianlang.de>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Creates a new direct message from the authenticating user to
+ * the user specified by id.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Adrian Lang <mail@adrianlang.de>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiDirectMessageNewAction extends ApiAuthAction
+{
+ var $source = null;
+ var $other = null;
+ var $content = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user!'), 404, $this->format);
+ return;
+ }
+
+ $this->source = $this->trimmed('source'); // Not supported by Twitter.
+
+ $reserved_sources = array('web', 'omb', 'mail', 'xmpp', 'api');
+ if (empty($thtis->source) || in_array($this->source, $reserved_sources)) {
+ $source = 'api';
+ }
+
+ $this->content = $this->trimmed('text');
+
+ $this->user = $this->auth_user;
+
+ $user_param = $this->trimmed('user');
+ $user_id = $this->arg('user_id');
+ $screen_name = $this->trimmed('screen_name');
+
+ if (isset($user_param) || isset($user_id) || isset($screen_name)) {
+ $this->other = $this->getTargetUser($user_param);
+ }
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Save the new message
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(
+ _('This method requires a POST.'),
+ 400,
+ $this->format
+ );
+ return;
+ }
+
+ if (empty($this->content)) {
+ $this->clientError(
+ _('No message text!'),
+ 406,
+ $this->format
+ );
+ } else {
+ $content_shortened = common_shorten_links($this->content);
+ if (Message::contentTooLong($content_shortened)) {
+ $this->clientError(
+ sprintf(
+ _('That\'s too long. Max message size is %d chars.'),
+ Message::maxContent()
+ ),
+ 406,
+ $this->format
+ );
+ return;
+ }
+ }
+
+ if (empty($this->other)) {
+ $this->clientError(_('Recipient user not found.'), 403, $this->format);
+ return;
+ } else if (!$this->user->mutuallySubscribed($this->other)) {
+ $this->clientError(
+ _('Can\'t send direct messages to users who aren\'t your friend.'),
+ 403,
+ $this->format
+ );
+ return;
+ } else if ($this->user->id == $this->other->id) {
+
+ // Note: sending msgs to yourself is allowed by Twitter
+
+ $errmsg = 'Don\'t send a message to yourself; ' .
+ 'just say it to yourself quietly instead.'
+
+ $this->clientError(_($errmsg), 403, $this->format);
+ return;
+ }
+
+ $message = Message::saveNew(
+ $this->user->id,
+ $this->other->id,
+ html_entity_decode($this->content, ENT_NOQUOTES, 'UTF-8'),
+ $this->source
+ );
+
+ if (is_string($message)) {
+ $this->serverError($message);
+ return;
+ }
+
+ mail_notify_message($message, $this->user, $this->other);
+
+ if ($this->format == 'xml') {
+ $this->showSingleXmlDirectMessage($message);
+ } elseif ($this->format == 'json') {
+ $this->showSingleJsondirectMessage($message);
+ }
+ }
+
+}
+
diff --git a/actions/apifavoritecreate.php b/actions/apifavoritecreate.php
new file mode 100644
index 000000000..a80a6492e
--- /dev/null
+++ b/actions/apifavoritecreate.php
@@ -0,0 +1,168 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Add a notice to a user's list of favorite notices via the API
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Favorites the status specified in the ID parameter as the authenticating user.
+ * Returns the favorite status when successful.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiFavoriteCreateAction extends ApiAuthAction
+{
+ var $notice = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+ $this->notice = Notice::staticGet($this->arg('id'));
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Check the format and show the user info
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(
+ _('This method requires a POST.'),
+ 400,
+ $this->format
+ );
+ return;
+ }
+
+ if (!in_array($this->format, array('xml', 'json'))) {
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ return;
+ }
+
+ if (empty($this->notice)) {
+ $this->clientError(
+ _('No status found with that ID.'),
+ 404,
+ $this->format
+ );
+ return;
+ }
+
+ // Note: Twitter lets you fave things repeatedly via API.
+
+ if ($this->user->hasFave($this->notice)) {
+ $this->clientError(
+ _('This status is already a favorite!'),
+ 403,
+ $this->format
+ );
+ return;
+ }
+
+ $fave = Fave::addNew($this->user, $this->notice);
+
+ if (empty($fave)) {
+ $this->clientError(
+ _('Could not create favorite.')
+ 403,
+ $this->format
+ );
+ return;
+ }
+
+ $this->notify($fave, $this->notice, $this->user);
+ $this->user->blowFavesCache();
+
+ if ($this->format == 'xml') {
+ $this->showSingleXmlStatus($this->notice);
+ } elseif ($this->format == 'json') {
+ $this->show_single_json_status($this->notice);
+ }
+ }
+
+ /**
+ * Notify the author of the favorite that the user likes their notice
+ *
+ * @param Favorite $fave the favorite in question
+ * @param Notice $notice the notice that's been faved
+ * @param User $user the user doing the favoriting
+ *
+ * @return void
+ */
+ function notify($fave, $notice, $user)
+ {
+ $other = User::staticGet('id', $notice->profile_id);
+ if ($other && $other->id != $user->id) {
+ if ($other->email && $other->emailnotifyfav) {
+ mail_notify_fave($other, $user, $notice);
+ }
+ // XXX: notify by IM
+ // XXX: notify by SMS
+ }
+ }
+
+}
diff --git a/actions/apifavoritedestroy.php b/actions/apifavoritedestroy.php
new file mode 100644
index 000000000..f131d1c7f
--- /dev/null
+++ b/actions/apifavoritedestroy.php
@@ -0,0 +1,150 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Remote a notice from a user's list of favorite notices via the API
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Un-favorites the status specified in the ID parameter as the authenticating user.
+ * Returns the un-favorited status in the requested format when successful.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiFavoriteDestroyAction extends ApiAuthAction
+{
+
+ var $notice = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+ $this->notice = Notice::staticGet($this->arg('id'));
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Check the format and show the user info
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(
+ _('This method requires a POST.'),
+ 400,
+ $this->format
+ );
+ return;
+ }
+
+ if (!in_array($this->format, array('xml', 'json'))) {
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ return;
+ }
+
+ if (empty($this->notice)) {
+ $this->clientError(
+ _('No status found with that ID.'),
+ 404,
+ $this->format
+ );
+ return;
+ }
+
+ $fave = new Fave();
+ $fave->user_id = $this->user->id;
+ $fave->notice_id = $this->notice->id;
+
+ if (!$fave->find(true)) {
+ $this->clientError(
+ _('That status is not a favorite!'),
+ 403,
+ $this->favorite
+ );
+ return;
+ }
+
+ $result = $fave->delete();
+
+ if (!$result) {
+ common_log_db_error($fave, 'DELETE', __FILE__);
+ $this->clientError(
+ _('Could not delete favorite.'),
+ 404,
+ $this->format
+ );
+ return;
+ }
+
+ $this->user->blowFavesCache();
+
+ if ($this->format == 'xml') {
+ $this->showSingleXmlStatus($this->notice);
+ } elseif ($this->format == 'json') {
+ $this->show_single_json_status($this->notice);
+ }
+ }
+
+}
diff --git a/actions/apifriendshipscreate.php b/actions/apifriendshipscreate.php
new file mode 100644
index 000000000..a824e734b
--- /dev/null
+++ b/actions/apifriendshipscreate.php
@@ -0,0 +1,137 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Subscribe to a user via the API
+ *
+ * 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 Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Allows the authenticating users to follow (subscribe) the user specified in
+ * the ID parameter. Returns the befriended user in the requested format when
+ * successful. Returns a string describing the failure condition when unsuccessful.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiFriendshipsCreateAction extends ApiAuthAction
+{
+ var $other = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+ $this->other = $this->getTargetUser($id);
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Check the format and show the user info
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(
+ _('This method requires a POST.'),
+ 400,
+ $this->format
+ );
+ return;
+ }
+
+ if (!in_array($this->format, array('xml', 'json'))) {
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ return;
+ }
+
+ if (empty($this->other)) {
+ $this->clientError(
+ _('Could not follow user: User not found.'),
+ 403,
+ $this->format
+ );
+ return;
+ }
+
+ if ($this->user->isSubscribed($this->other)) {
+ $errmsg = sprintf(
+ _('Could not follow user: %s is already on your list.'),
+ $this->other->nickname
+ );
+ $this->clientError($errmsg, 403, $this->format);
+ return;
+ }
+
+ $result = subs_subscribe_to($this->user, $this->other);
+
+ if (is_string($result)) {
+ $this->clientError($result, 403, $this->format);
+ return;
+ }
+
+ $this->initDocument($this->format);
+ $this->showProfile($this->other, $this->format);
+ $this->endDocument($this->format);
+ }
+
+}
diff --git a/actions/apifriendshipsdestroy.php b/actions/apifriendshipsdestroy.php
new file mode 100644
index 000000000..3d9b7e001
--- /dev/null
+++ b/actions/apifriendshipsdestroy.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Unsubscribe to a user via API
+ *
+ * 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 Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Allows the authenticating users to unfollow (unsubscribe) the user specified in
+ * the ID parameter. Returns the unfollowed user in the requested format when
+ * successful. Returns a string describing the failure condition when unsuccessful.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiFriendshipsDestroyAction extends ApiAuthAction
+{
+ var $other = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+ $this->other = $this->getTargetUser($id);
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Check the format and show the user info
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(
+ _('This method requires a POST.'),
+ 400,
+ $this->format
+ );
+ return;
+ }
+
+ if (!in_array($this->format, array('xml', 'json'))) {
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ return;
+ }
+
+ if (empty($this->other)) {
+ $this->clientError(
+ _('Could not unfollow user: User not found.'),
+ 403,
+ $this->format
+ );
+ return;
+ }
+
+ // Don't allow unsubscribing from yourself!
+
+ if ($this->user->id == $this->other->id) {
+ $this->clientError(
+ _("You cannot unfollow yourself!"),
+ 403,
+ $this->format
+ );
+ return;
+ }
+
+ $result = subs_unsubscribe_user($this->user, $this->other->nickname);
+
+ if (is_string($result)) {
+ $this->clientError($result, 403, $this->format);
+ return;
+ }
+
+ $this->initDocument($this->format);
+ $this->showProfile($this->other, $this->format);
+ $this->endDocument($this->format);
+ }
+
+}
diff --git a/actions/apifriendshipsexists.php b/actions/apifriendshipsexists.php
new file mode 100644
index 000000000..ae50c512c
--- /dev/null
+++ b/actions/apifriendshipsexists.php
@@ -0,0 +1,128 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show whether there is a friendship between two users
+ *
+ * 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 Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/api.php';
+
+/**
+ * Tests for the existence of friendship between two users. Will return true if
+ * user_a follows user_b, otherwise will return false.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiFriendshipsExistsAction extends ApiAction
+{
+ var $user_a = null;
+ var $user_b = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $user_a_id = $this->trimmed('user_a');
+ $user_b_id = $this->trimmed('user_b');
+
+ common_debug("user_a = " . $user_a_id);
+ common_debug("user_b = " . $user_b_id);
+
+
+ $this->user_a = $this->getTargetUser($user_a_id);
+
+ if (empty($this->user_a)) {
+ common_debug('gargargra');
+ }
+
+ $this->user_b = $this->getTargetUser($user_b_id);
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Check the format and show the user info
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (empty($this->user_a) || empty($this->user_b)) {
+ $this->clientError(
+ _('Two user ids or screen_names must be supplied.'),
+ 400,
+ $this->format
+ );
+ return;
+ }
+
+ $result = $this->user_a->isSubscribed($this->user_b);
+
+ switch ($this->format) {
+ case 'xml':
+ $this->initDocument('xml');
+ $this->element('friends', null, $result);
+ $this->endDocument('xml');
+ break;
+ case 'json':
+ $this->initDocument('json');
+ print json_encode($result);
+ $this->endDocument('json');
+ break;
+ default:
+ break;
+ }
+ }
+
+}
diff --git a/actions/apifriendshipsshow.php b/actions/apifriendshipsshow.php
new file mode 100644
index 000000000..8fc436738
--- /dev/null
+++ b/actions/apifriendshipsshow.php
@@ -0,0 +1,168 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show information about the relationship between two users
+ *
+ * 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 Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apibareauth.php';
+
+/**
+ * Outputs detailed information about the relationship between two users
+ *
+ * @category API
+ * @package StatusNet
+ * @author Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiFriendshipsShowAction extends ApiBareAuthAction
+{
+ var $source = null;
+ var $target = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $source_id = (int)$this->trimmed('source_id');
+ $source_screen_name = $this->trimmed('source_screen_name');
+ $target_id = (int)$this->trimmed('target_id');
+ $target_screen_name = $this->trimmed('target_screen_name');
+
+ if (!empty($source_id)) {
+ $this->source = User::staticGet($source_id);
+ } elseif (!empty($source_screen_name)) {
+ $this->source = User::staticGet('nickname', $source_screen_name);
+ } else {
+ $this->source = $this->auth_user;
+ }
+
+ if (!empty($target_id)) {
+ $this->target = User::staticGet($target_id);
+ } elseif (!empty($target_screen_name)) {
+ $this->target = User::staticGet('nickname', $target_screen_name);
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Determines whether this API resource requires auth. Overloaded to look
+ * return true in case source_id and source_screen_name are both empty
+ *
+ * @return boolean true or false
+ */
+
+ function requiresAuth()
+ {
+ if (common_config('site', 'private')) {
+ return true;
+ }
+
+ $source_id = $this->trimmed('source_id');
+ $source_screen_name = $this->trimmed('source_screen_name');
+
+ if (empty($source_id) && empty($source_screen_name)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Check the format and show the user info
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (!in_array($this->format, array('xml', 'json'))) {
+ $this->clientError(_('API method not found!'), 404);
+ return;
+ }
+
+ if (empty($this->source)) {
+ $this->clientError(
+ _('Could not determine source user.'),
+ 404
+ );
+ return;
+ }
+
+ if (empty($this->target)) {
+ $this->clientError(
+ _('Could not find target user.'),
+ 404
+ );
+ return;
+ }
+
+ $result = $this->twitterRelationshipArray($this->source, $this->target);
+
+ switch ($this->format) {
+ case 'xml':
+ $this->initDocument('xml');
+ $this->showTwitterXmlRelationship($result[relationship]);
+ $this->endDocument('xml');
+ break;
+ case 'json':
+ $this->initDocument('json');
+ print json_encode($result);
+ $this->endDocument('json');
+ break;
+ default:
+ break;
+ }
+
+ }
+
+}
diff --git a/actions/apigroupcreate.php b/actions/apigroupcreate.php
new file mode 100644
index 000000000..cdb2afb5b
--- /dev/null
+++ b/actions/apigroupcreate.php
@@ -0,0 +1,381 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Create a group via the API
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Make a new group. Sets the authenticated user as the administrator of the group.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiGroupCreateAction extends ApiAuthAction
+{
+ var $group = null;
+ var $nickname = null;
+ var $fullname = null;
+ var $homepage = null;
+ var $description = null;
+ var $location = null;
+ var $aliasstring = null;
+ var $aliases = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+
+ $this->nickname = $this->arg('nickname');
+ $this->fullname = $this->arg('full_name');
+ $this->homepage = $this->arg('homepage');
+ $this->description = $this->arg('description');
+ $this->location = $this->arg('location');
+ $this->aliasstring = $this->arg('aliases');
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Save the new group
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (!common_config('inboxes', 'enabled')) {
+ $this->serverError(
+ _('Inboxes must be enabled for groups to work'),
+ 400,
+ $this->format
+ );
+ return false;
+ }
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(
+ _('This method requires a POST.'),
+ 400,
+ $this->format
+ );
+ return;
+ }
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user!'), 404, $this->format);
+ return;
+ }
+
+ if ($this->validateParams() == false) {
+ return;
+ }
+
+ $group = new User_group();
+
+ $group->query('BEGIN');
+
+ $group->nickname = $this->nickname;
+ $group->fullname = $this->fullname;
+ $group->homepage = $this->homepage;
+ $group->description = $this->description;
+ $group->location = $this->location;
+ $group->created = common_sql_now();
+
+ $result = $group->insert();
+
+ if (!$result) {
+ common_log_db_error($group, 'INSERT', __FILE__);
+ $this->serverError(
+ _('Could not create group.'),
+ 500,
+ $this->format
+ );
+ return;
+ }
+
+ $result = $group->setAliases($this->aliases);
+
+ if (!$result) {
+ $this->serverError(
+ _('Could not create aliases.'),
+ 500,
+ $this->format
+ );
+ return;
+ }
+
+ $member = new Group_member();
+
+ $member->group_id = $group->id;
+ $member->profile_id = $this->user->id;
+ $member->is_admin = 1;
+ $member->created = $group->created;
+
+ $result = $member->insert();
+
+ if (!$result) {
+ common_log_db_error($member, 'INSERT', __FILE__);
+ $this->serverError(
+ _('Could not set group membership.'),
+ 500,
+ $this->format
+ );
+ return;
+ }
+
+ $group->query('COMMIT');
+
+ switch($this->format) {
+ case 'xml':
+ $this->showSingleXmlGroup($group);
+ break;
+ case 'json':
+ $this->showSingleJsonGroup($group);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+
+ }
+
+ /**
+ * Validate params for the new group
+ *
+ * @return void
+ */
+
+ function validateParams()
+ {
+ $valid = Validate::string(
+ $this->nickname, array(
+ 'min_length' => 1,
+ 'max_length' => 64,
+ 'format' => NICKNAME_FMT
+ )
+ );
+
+ if (!$valid) {
+ $this->clientError(
+ _(
+ 'Nickname must have only lowercase letters ' .
+ 'and numbers and no spaces.'
+ ),
+ 403,
+ $this->format
+ );
+ return false;
+ } elseif ($this->groupNicknameExists($this->nickname)) {
+ $this->clientError(
+ _('Nickname already in use. Try another one.'),
+ 403,
+ $this->format
+ );
+ return false;
+ } else if (!User_group::allowedNickname($this->nickname)) {
+ $this->clientError(
+ _('Not a valid nickname.'),
+ 403,
+ $this->format
+ );
+ return false;
+
+ } elseif (
+ !is_null($this->homepage)
+ && strlen($this->homepage) > 0
+ && !Validate::uri(
+ $this->homepage, array(
+ 'allowed_schemes' =>
+ array('http', 'https')
+ )
+ )) {
+ $this->clientError(
+ _('Homepage is not a valid URL.'),
+ 403,
+ $this->format
+ );
+ return false;
+ } elseif (
+ !is_null($this->fullname)
+ && mb_strlen($this->fullname) > 255) {
+ $this->clientError(
+ _('Full name is too long (max 255 chars).'),
+ 403,
+ $this->format
+ );
+ return false;
+ } elseif (User_group::descriptionTooLong($this->description)) {
+ $this->clientError(
+ sprintf(
+ _('Description is too long (max %d chars).'),
+ User_group::maxDescription()
+ ),
+ 403,
+ $this->format
+ );
+ return false;
+ } elseif (
+ !is_null($this->location)
+ && mb_strlen($this->location) > 255) {
+ $this->clientError(
+ _('Location is too long (max 255 chars).'),
+ 403,
+ $this->format
+ );
+ return false;
+ }
+
+ if (!empty($this->aliasstring)) {
+ $this->aliases = array_map(
+ 'common_canonical_nickname',
+ array_unique(preg_split('/[\s,]+/', $this->aliasstring))
+ );
+ } else {
+ $this->aliases = array();
+ }
+
+ if (count($this->aliases) > common_config('group', 'maxaliases')) {
+ $this->clientError(
+ sprintf(
+ _('Too many aliases! Maximum %d.'),
+ common_config('group', 'maxaliases')
+ ),
+ 403,
+ $this->format
+ );
+ return false;
+ }
+
+ foreach ($this->aliases as $alias) {
+
+ $valid = Validate::string(
+ $alias, array(
+ 'min_length' => 1,
+ 'max_length' => 64,
+ 'format' => NICKNAME_FMT
+ )
+ );
+
+ if (!$valid) {
+ $this->clientError(
+ sprintf(_('Invalid alias: "%s"'), $alias),
+ 403,
+ $this->format
+ );
+ return false;
+ }
+ if ($this->groupNicknameExists($alias)) {
+ $this->clientError(
+ sprintf(
+ _('Alias "%s" already in use. Try another one.'),
+ $alias
+ ),
+ 403,
+ $this->format
+ );
+ return false;
+ }
+
+ // XXX assumes alphanum nicknames
+
+ if (strcmp($alias, $this->nickname) == 0) {
+ $this->clientError(
+ _('Alias can\'t be the same as nickname.'),
+ 403,
+ $this->format
+ );
+ return false;
+ }
+ }
+
+ // Evarything looks OK
+
+ return true;
+ }
+
+ /**
+ * Check to see whether a nickname is already in use by a group
+ *
+ * @param String $nickname The nickname in question
+ *
+ * @return boolean true or false
+ */
+
+ function groupNicknameExists($nickname)
+ {
+ $group = User_group::staticGet('nickname', $nickname);
+
+ if (!empty($group)) {
+ return true;
+ }
+
+ $alias = Group_alias::staticGet('alias', $nickname);
+
+ if (!empty($alias)) {
+ return true;
+ }
+
+ return false;
+ }
+
+}
diff --git a/actions/apigroupismember.php b/actions/apigroupismember.php
new file mode 100644
index 000000000..a8a40a6b3
--- /dev/null
+++ b/actions/apigroupismember.php
@@ -0,0 +1,122 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Check to see whether a user a member of a group
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apibareauth.php';
+
+/**
+ * Returns whether a user is a member of a specified group.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiGroupIsMemberAction extends ApiBareAuthAction
+{
+ var $group = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->getTargetUser(null);
+ $this->group = $this->getTargetGroup(null);
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Save the new message
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user!'), 404, $this->format);
+ return;
+ }
+
+ if (empty($this->group)) {
+ $this->clientError('Group not found!', 404, $this->format);
+ return false;
+ }
+
+ $is_member = $this->user->isMember($this->group);
+
+ switch($this->format) {
+ case 'xml':
+ $this->initDocument('xml');
+ $this->element('is_member', null, $is_member);
+ $this->endDocument('xml');
+ break;
+ case 'json':
+ $this->initDocument('json');
+ $this->showJsonObjects(array('is_member' => $is_member));
+ $this->endDocument('json');
+ break;
+ default:
+ $this->clientError(
+ _('API method not found!'),
+ 400,
+ $this->format
+ );
+ break;
+ }
+ }
+
+}
diff --git a/actions/apigroupjoin.php b/actions/apigroupjoin.php
new file mode 100644
index 000000000..071cd9290
--- /dev/null
+++ b/actions/apigroupjoin.php
@@ -0,0 +1,163 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Join a group via the API
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Joins the authenticated user to the group speicified by ID
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiGroupJoinAction extends ApiAuthAction
+{
+ var $group = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+ $this->group = $this->getTargetGroup($this->arg('id'));
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Save the new message
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(
+ _('This method requires a POST.'),
+ 400,
+ $this->format
+ );
+ return;
+ }
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user!'), 404, $this->format);
+ return;
+ }
+
+ if (empty($this->group)) {
+ $this->clientError('Group not found!', 404, $this->format);
+ return false;
+ }
+
+ if ($this->user->isMember($this->group)) {
+ $this->clientError(
+ _('You are already a member of that group.'),
+ 403,
+ $this->format
+ );
+ return;
+ }
+
+ if (Group_block::isBlocked($this->group, $this->user->getProfile())) {
+ $this->clientError(
+ _('You have been blocked from that group by the admin.'),
+ 403,
+ $this->format
+ );
+ return;
+ }
+
+ $member = new Group_member();
+
+ $member->group_id = $this->group->id;
+ $member->profile_id = $this->user->id;
+ $member->created = common_sql_now();
+
+ $result = $member->insert();
+
+ if (!$result) {
+ common_log_db_error($member, 'INSERT', __FILE__);
+ $this->serverError(
+ sprintf(
+ _('Could not join user %s to group %s.'),
+ $this->user->nickname,
+ $this->group->nickname
+ )
+ );
+ return;
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->show_single_xml_group($this->group);
+ break;
+ case 'json':
+ $this->showSingleJsonGroup($this->group);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+
+}
diff --git a/actions/apigroupleave.php b/actions/apigroupleave.php
new file mode 100644
index 000000000..0d4bb9e4d
--- /dev/null
+++ b/actions/apigroupleave.php
@@ -0,0 +1,149 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Leave a group via the API
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Removes the authenticated user from the group specified by ID
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiGroupLeaveAction extends ApiAuthAction
+{
+ var $group = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+ $this->group = $this->getTargetGroup($this->arg('id'));
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Save the new message
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(
+ _('This method requires a POST.'),
+ 400,
+ $this->format
+ );
+ return;
+ }
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user!'), 404, $this->format);
+ return;
+ }
+
+ if (empty($this->group)) {
+ $this->clientError('Group not found!', 404, $this->format);
+ return false;
+ }
+
+ $member = new Group_member();
+
+ $member->group_id = $this->group->id;
+ $member->profile_id = $this->auth->id;
+
+ if (!$member->find(true)) {
+ $this->serverError(_('You are not a member of this group.'));
+ return;
+ }
+
+ $result = $member->delete();
+
+ if (!$result) {
+ common_log_db_error($member, 'INSERT', __FILE__);
+ $this->serverError(
+ sprintf(
+ _('Could not remove user %s to group %s.'),
+ $this->user->nickname,
+ $this->$group->nickname
+ )
+ );
+ return;
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->show_single_xml_group($this->group);
+ break;
+ case 'json':
+ $this->showSingleJsonGroup($this->group);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+
+}
diff --git a/actions/apigrouplist.php b/actions/apigrouplist.php
new file mode 100644
index 000000000..c529c1e40
--- /dev/null
+++ b/actions/apigrouplist.php
@@ -0,0 +1,223 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Check to see whether a user a member of a group
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apibareauth.php';
+
+/**
+ * Returns whether a user is a member of a specified group.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiGroupListAction extends ApiBareAuthAction
+{
+ var $groups = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->getTargetUser($id);
+ $this->groups = $this->getGroups();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Show the user's groups
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user!'), 404, $this->format);
+ return;
+ }
+
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_("%s's groups"), $this->user->nickname);
+ $taguribase = common_config('integration', 'taguri');
+ $id = "tag:$taguribase:Groups";
+ $link = common_local_url(
+ 'usergroups',
+ array('nickname' => $this->user->nickname)
+ );
+ $subtitle = sprintf(
+ _("Groups %s is a member of on %s."),
+ $this->user->nickname,
+ $sitename
+ );
+
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlGroups($this->groups);
+ break;
+ case 'rss':
+ $this->showRssGroups($this->groups, $title, $link, $subtitle);
+ break;
+ case 'atom':
+ $selfuri = common_root_url() . 'api/statusnet/groups/list/' .
+ $this->user->id . '.atom';
+ $this->showAtomGroups(
+ $this->groups,
+ $title,
+ $id,
+ $link,
+ $subtitle,
+ $selfuri
+ );
+ break;
+ case 'json':
+ $this->showJsonGroups($this->groups);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+
+ }
+
+ /**
+ * Get groups
+ *
+ * @return array groups
+ */
+
+ function getGroups()
+ {
+ $groups = array();
+
+ $group = $this->user->getGroups(
+ ($this->page - 1) * $this->count,
+ $this->count,
+ $this->since_id,
+ $this->max_id,
+ $this->since
+ );
+
+ while ($group->fetch()) {
+ $groups[] = clone($group);
+ }
+
+ return $groups;
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this feed last modified?
+ *
+ * @return string datestamp of the latest group the user has joined
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->groups) && (count($this->groups) > 0)) {
+ return strtotime($this->groups[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this list of groups
+ *
+ * Returns an Etag based on the action name, language, user ID and
+ * timestamps of the first and last group the user has joined
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->groups) && (count($this->groups) > 0)) {
+
+ $last = count($this->groups) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->user->id,
+ strtotime($this->groups[0]->created),
+ strtotime($this->groups[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apigrouplistall.php b/actions/apigrouplistall.php
new file mode 100644
index 000000000..89469f36f
--- /dev/null
+++ b/actions/apigrouplistall.php
@@ -0,0 +1,208 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show the newest groups
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/api.php';
+
+/**
+ * Returns of the lastest 20 groups for the site
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiGroupListAllAction extends ApiAction
+{
+ var $groups = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->getTargetUser($id);
+ $this->groups = $this->getGroups();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Show the user's groups
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_("%s groups"), $sitename);
+ $taguribase = common_config('integration', 'taguri');
+ $id = "tag:$taguribase:Groups";
+ $link = common_local_url('groups');
+ $subtitle = sprintf(_("groups on %s"), $sitename);
+
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlGroups($this->groups);
+ break;
+ case 'rss':
+ $this->showRssGroups($this->groups, $title, $link, $subtitle);
+ break;
+ case 'atom':
+ $selfuri = common_root_url() .
+ 'api/statusnet/groups/list_all.atom';
+ $this->showAtomGroups(
+ $this->groups,
+ $title,
+ $id,
+ $link,
+ $subtitle,
+ $selfuri
+ );
+ break;
+ case 'json':
+ $this->showJsonGroups($this->groups);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+
+ }
+
+ /**
+ * Get groups
+ *
+ * @return array groups
+ */
+
+ function getGroups()
+ {
+ $groups = array();
+
+ // XXX: Use the $page, $count, $max_id, $since_id, and $since parameters
+
+ $group = new User_group();
+ $group->orderBy('created DESC');
+ $group->find();
+
+ while ($group->fetch()) {
+ $groups[] = clone($group);
+ }
+
+ return $groups;
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this feed last modified?
+ *
+ * @return string datestamp of the site's latest group
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->groups) && (count($this->groups) > 0)) {
+ return strtotime($this->groups[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this list of groups
+ *
+ * Returns an Etag based on the action name, language, and
+ * timestamps of the first and last group the user has joined
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->groups) && (count($this->groups) > 0)) {
+
+ $last = count($this->groups) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ strtotime($this->groups[0]->created),
+ strtotime($this->groups[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apigroupmembership.php b/actions/apigroupmembership.php
new file mode 100644
index 000000000..b31e47b39
--- /dev/null
+++ b/actions/apigroupmembership.php
@@ -0,0 +1,192 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * List a group's members
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/api.php';
+
+/**
+ * List 20 newest members of the group specified by name or ID.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiGroupMembershipAction extends ApiAction
+{
+ var $group = null;
+ var $profiles = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->group = $this->getTargetGroup($this->arg('id'));
+ $this->profiles = $this->getProfiles();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Show the members of the group
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ // XXX: RSS and Atom
+
+ switch($this->format) {
+ case 'xml':
+ $this->showTwitterXmlUsers($this->profiles);
+ break;
+ case 'json':
+ $this->showJsonUsers($this->profiles);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+
+ /**
+ * Fetch the members of a group
+ *
+ * @return array $profiles list of profiles
+ */
+
+ function getProfiles()
+ {
+ $profiles = array();
+
+ $profile = $this->group->getMembers(
+ ($this->page - 1) * $this->count,
+ $this->count,
+ $this->since_id,
+ $this->max_id,
+ $this->since
+ );
+
+ while ($profile->fetch()) {
+ $profiles[] = clone($profile);
+ }
+
+ return $profiles;
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this list of profiles last modified?
+ *
+ * @return string datestamp of the lastest profile in the group
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->profiles) && (count($this->profiles) > 0)) {
+ return strtotime($this->profiles[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this list of groups
+ *
+ * Returns an Etag based on the action name, language
+ * the group id, and timestamps of the first and last
+ * user who has joined the group
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->profiles) && (count($this->profiles) > 0)) {
+
+ $last = count($this->profiles) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->group->id,
+ strtotime($this->profiles[0]->created),
+ strtotime($this->profiles[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apigroupshow.php b/actions/apigroupshow.php
new file mode 100644
index 000000000..2bdb22bc4
--- /dev/null
+++ b/actions/apigroupshow.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show information about a group
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/api.php';
+
+/**
+ * Outputs detailed information about the group specified by ID
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiGroupShowAction extends ApiAction
+{
+ var $group = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->group = $this->getTargetGroup($this->arg('id'));
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Check the format and show the user info
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (empty($this->group)) {
+ $this->clientError(
+ 'Group not found!',
+ 404,
+ $this->format
+ );
+ return;
+ }
+
+ switch($this->format) {
+ case 'xml':
+ $this->show_single_xml_group($this->group);
+ break;
+ case 'json':
+ $this->showSingleJsonGroup($this->group);
+ break;
+ default:
+ $this->clientError(_('API method not found!'), 404, $this->format);
+ break;
+ }
+
+ }
+
+ /**
+ * When was this group last modified?
+ *
+ * @return string datestamp of the latest notice in the stream
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->group)) {
+ return strtotime($this->group->modified);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this group
+ *
+ * Returns an Etag based on the action name, language, and
+ * timestamps of the notice
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->group)) {
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->group->id,
+ strtotime($this->group->modified))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apihelptest.php b/actions/apihelptest.php
new file mode 100644
index 000000000..e4ef55f2e
--- /dev/null
+++ b/actions/apihelptest.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Test that you can connect to the API
+ *
+ * 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>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/api.php';
+
+/**
+ * Returns the string "ok" in the requested format with a 200 OK HTTP status code.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiHelpTestAction extends ApiAction
+{
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if ($this->format == 'xml') {
+ $this->initDocument('xml');
+ $this->element('ok', null, 'true');
+ $this->endDocument('xml');
+ } elseif ($this->format == 'json') {
+ $this->initDocument('json');
+ print '"ok"';
+ $this->endDocument('json');
+ } else {
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ }
+ }
+
+}
+
diff --git a/actions/apistatusesdestroy.php b/actions/apistatusesdestroy.php
new file mode 100644
index 000000000..8dc8793b5
--- /dev/null
+++ b/actions/apistatusesdestroy.php
@@ -0,0 +1,154 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Destroy a notice through the API
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Tom Blankenship <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Deletes one of the authenticating user's statuses (notices).
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Tom Blankenship <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiStatusesDestroyAction extends ApiAuthAction
+{
+ var $status = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+ $this->notice_id = (int)$this->trimmed('id');
+
+ if (empty($notice_id)) {
+ $this->notice_id = (int)$this->arg('id');
+ }
+
+ $this->notice = Notice::staticGet((int)$this->notice_id);
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Delete the notice and all related replies
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (!in_array($this->format, array('xml', 'json'))) {
+ $this->clientError(_('API method not found!'), $code = 404);
+ return;
+ }
+
+ if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
+ $this->clientError(_('This method requires a POST or DELETE.'),
+ 400, $this->format);
+ return;
+ }
+
+ if (empty($this->notice)) {
+ $this->clientError(_('No status found with that ID.'),
+ 404, $this->format);
+ return;
+ }
+
+ if ($this->user->id == $this->notice->profile_id) {
+ $replies = new Reply;
+ $replies->get('notice_id', $this->notice_id);
+ $replies->delete();
+ $this->notice->delete();
+
+ if ($this->format == 'xml') {
+ $this->showSingleXmlStatus($this->notice);
+ } elseif ($this->format == 'json') {
+ $this->show_single_json_status($this->notice);
+ }
+ } else {
+ $this->clientError(_('You may not delete another user\'s status.'),
+ 403, $this->format);
+ }
+
+ $this->showNotice();
+ }
+
+ /**
+ * Show the deleted notice
+ *
+ * @return void
+ */
+
+ function showNotice()
+ {
+ if (!empty($this->notice)) {
+ if ($this->format == 'xml') {
+ $this->showSingleXmlStatus($this->notice);
+ } elseif ($this->format == 'json') {
+ $this->show_single_json_status($this->notice);
+ }
+ }
+ }
+
+}
diff --git a/actions/apistatusesshow.php b/actions/apistatusesshow.php
new file mode 100644
index 000000000..3be22ca59
--- /dev/null
+++ b/actions/apistatusesshow.php
@@ -0,0 +1,206 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a notice (as a Twitter-style status)
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Tom Blankenship <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/api.php';
+
+/**
+ * Returns the notice specified by id as a Twitter-style status and inline user
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Tom Blankenship <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiStatusesShowAction extends ApiAction
+{
+
+ var $notice_id = null;
+ var $notice = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ // 'id' is an undocumented parameter in Twitter's API. Several
+ // clients make use of it, so we support it too.
+
+ // show.json?id=12345 takes precedence over /show/12345.json
+
+ $this->notice_id = (int)$this->trimmed('id');
+
+ if (empty($notice_id)) {
+ $this->notice_id = (int)$this->arg('id');
+ }
+
+ $this->notice = Notice::staticGet((int)$this->notice_id);
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Check the format and show the notice
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (!in_array($this->format, array('xml', 'json'))) {
+ $this->clientError(_('API method not found!'), $code = 404);
+ return;
+ }
+
+ $this->showNotice();
+ }
+
+ /**
+ * Show the notice
+ *
+ * @return void
+ */
+
+ function showNotice()
+ {
+ if (!empty($this->notice)) {
+ if ($this->format == 'xml') {
+ $this->showSingleXmlStatus($this->notice);
+ } elseif ($this->format == 'json') {
+ $this->show_single_json_status($this->notice);
+ }
+ } else {
+
+ // XXX: Twitter just sets a 404 header and doens't bother
+ // to return an err msg
+
+ $deleted = Deleted_notice::staticGet($this->notice_id);
+
+ if (!empty($deleted)) {
+ $this->clientError(
+ _('Status deleted.'),
+ 410,
+ $this->format
+ );
+ } else {
+ $this->clientError(
+ _('No status with that ID found.'),
+ 404,
+ $this->format
+ );
+ }
+ }
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this notice last modified?
+ *
+ * @return string datestamp of the latest notice in the stream
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->notice)) {
+ return strtotime($this->notice->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this notice
+ *
+ * Returns an Etag based on the action name, language, and
+ * timestamps of the notice
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->notice)) {
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->notice->id,
+ strtotime($this->notice->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apistatusesupdate.php b/actions/apistatusesupdate.php
new file mode 100644
index 000000000..0d71e1512
--- /dev/null
+++ b/actions/apistatusesupdate.php
@@ -0,0 +1,241 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Post a notice (update your status) through the API
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Tom Blankenship <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apiauth.php';
+
+/**
+ * Updates the authenticating user's status (posts a notice).
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Tom Blankenship <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiStatusesUpdateAction extends ApiAuthAction
+{
+ var $source = null;
+ var $status = null;
+ var $in_reply_to_status_id = null;
+
+ static $reserved_sources = array('web', 'omb', 'mail', 'xmpp', 'api');
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user!'), 404, $this->format);
+ return false;
+ }
+
+ $this->status = $this->trimmed('status');
+
+ if (empty($this->status)) {
+ $this->clientError(
+ 'Client must provide a \'status\' parameter with a value.',
+ 400,
+ $this->format
+ );
+
+ return false;
+ }
+
+ $this->source = $this->trimmed('source');
+
+ if (empty($this->source) || in_array($source, $this->reserved_sources)) {
+ $this->source = 'api';
+ }
+
+ $this->in_reply_to_status_id
+ = intval($this->trimmed('in_reply_to_status_id'));
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Make a new notice for the update, save it, and show it
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if ($_SERVER['REQUEST_METHOD'] != 'POST') {
+ $this->clientError(
+ _('This method requires a POST.'),
+ 400, $this->format
+ );
+ return;
+ }
+
+ $status_shortened = common_shorten_links($this->status);
+
+ if (Notice::contentTooLong($status_shortened)) {
+
+ // Note: Twitter truncates anything over 140, flags the status
+ // as "truncated."
+
+ $this->clientError(
+ sprintf(
+ _('That\'s too long. Max notice size is %d chars.'),
+ Notice::maxContent()
+ ),
+ 406,
+ $this->format
+ );
+
+ return;
+ }
+
+ // Check for commands
+
+ $inter = new CommandInterpreter();
+ $cmd = $inter->handle_command($this->user, $status_shortened);
+
+ if ($cmd) {
+
+ if ($this->supported($cmd)) {
+ $cmd->execute(new Channel());
+ }
+
+ // Cmd not supported? Twitter just returns your latest status.
+ // And, it returns your last status whether the cmd was successful
+ // or not!
+
+ $this->notice = $this->user->getCurrentNotice();
+
+ } else {
+
+ $reply_to = null;
+
+ if (!empty($this->in_reply_to_status_id)) {
+
+ // Check whether notice actually exists
+
+ $reply = Notice::staticGet($this->in_reply_to_status_id);
+
+ if ($reply) {
+ $reply_to = $this->in_reply_to_status_id;
+ } else {
+ $this->clientError(
+ _('Not found'),
+ $code = 404,
+ $this->format
+ );
+ return;
+ }
+ }
+
+ $this->notice = Notice::saveNew(
+ $this->user->id,
+ html_entity_decode($this->status, ENT_NOQUOTES, 'UTF-8'),
+ $this->source,
+ 1,
+ $reply_to
+ );
+
+ common_broadcast_notice($this->notice);
+ }
+
+ $this->showNotice();
+ }
+
+ /**
+ * Show the resulting notice
+ *
+ * @return void
+ */
+
+ function showNotice()
+ {
+ if (!empty($this->notice)) {
+ if ($this->format == 'xml') {
+ $this->showSingleXmlStatus($this->notice);
+ } elseif ($this->format == 'json') {
+ $this->show_single_json_status($this->notice);
+ }
+ }
+ }
+
+ /**
+ * Is this command supported when doing an update from the API?
+ *
+ * @param string $cmd the command to check for
+ *
+ * @return boolean true or false
+ */
+
+ function supported($cmd)
+ {
+ static $cmdlist = array('MessageCommand', 'SubCommand', 'UnsubCommand',
+ 'FavCommand', 'OnCommand', 'OffCommand');
+
+ if (in_array(get_class($cmd), $cmdlist)) {
+ return true;
+ }
+
+ return false;
+ }
+
+}
diff --git a/actions/apistatusnetconfig.php b/actions/apistatusnetconfig.php
new file mode 100644
index 000000000..ed1d151bf
--- /dev/null
+++ b/actions/apistatusnetconfig.php
@@ -0,0 +1,142 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Dump of configuration variables
+ *
+ * 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>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/api.php';
+
+/**
+ * Gives a full dump of configuration variables for this instance
+ * of StatusNet, minus variables that may be security-sensitive (like
+ * passwords).
+ * URL: http://identi.ca/api/statusnet/config.(xml|json)
+ * Formats: xml, json
+ *
+ * @category API
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiStatusnetConfigAction extends ApiAction
+{
+ var $keys = array(
+ 'site' => array('name', 'server', 'theme', 'path', 'fancy', 'language',
+ 'email', 'broughtby', 'broughtbyurl', 'closed',
+ 'inviteonly', 'private'),
+ 'license' => array('url', 'title', 'image'),
+ 'nickname' => array('featured'),
+ 'throttle' => array('enabled', 'count', 'timespan'),
+ 'xmpp' => array('enabled', 'server', 'user')
+ );
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ switch ($this->format) {
+ case 'xml':
+ $this->initDocument('xml');
+ $this->elementStart('config');
+
+ // XXX: check that all sections and settings are legal XML elements
+
+ common_debug(var_export($this->keys, true));
+
+ foreach ($this->keys as $section => $settings) {
+ $this->elementStart($section);
+ foreach ($settings as $setting) {
+ $value = common_config($section, $setting);
+ if (is_array($value)) {
+ $value = implode(',', $value);
+ } else if ($value === false) {
+ $value = 'false';
+ } else if ($value === true) {
+ $value = 'true';
+ }
+ $this->element($setting, null, $value);
+ }
+ $this->elementEnd($section);
+ }
+ $this->elementEnd('config');
+ $this->endDocument('xml');
+ break;
+ case 'json':
+ $result = array();
+ foreach ($this->keys as $section => $settings) {
+ $result[$section] = array();
+ foreach ($settings as $setting) {
+ $result[$section][$setting]
+ = common_config($section, $setting);
+ }
+ }
+ $this->initDocument('json');
+ $this->showJsonObjects($result);
+ $this->endDocument('json');
+ break;
+ default:
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+
+}
+
diff --git a/actions/apistatusnetversion.php b/actions/apistatusnetversion.php
new file mode 100644
index 000000000..e73ab983b
--- /dev/null
+++ b/actions/apistatusnetversion.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * A version stamp for the API
+ *
+ * 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>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/api.php';
+
+/**
+ * Returns a version number for this version of StatusNet, which
+ * should make things a bit easier for upgrades.
+ * URL: http://identi.ca/api/statusnet/version.(xml|json)
+ * Formats: xml, js
+ *
+ * @category API
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiStatusnetVersionAction extends ApiAction
+{
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ switch ($this->format) {
+ case 'xml':
+ $this->initDocument('xml');
+ $this->element('version', null, STATUSNET_VERSION);
+ $this->endDocument('xml');
+ break;
+ case 'json':
+ $this->initDocument('json');
+ print '"'.STATUSNET_VERSION.'"';
+ $this->endDocument('json');
+ break;
+ default:
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+
+}
+
diff --git a/actions/apisubscriptions.php b/actions/apisubscriptions.php
new file mode 100644
index 000000000..bc68dd192
--- /dev/null
+++ b/actions/apisubscriptions.php
@@ -0,0 +1,266 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Base class for showing subscription information in the API
+ *
+ * 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 Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apibareauth.php';
+
+/**
+ * This class outputs a list of profiles as Twitter-style user and status objects.
+ * It is used by the API methods /api/statuses/(friends|followers). To support the
+ * social graph methods it also can output a simple list of IDs.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiSubscriptionsAction extends ApiBareAuthAction
+{
+ var $profiles = null;
+ var $tag = null;
+ var $lite = null;
+ var $ids_only = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->tag = $this->arg('tag');
+
+ // Note: Twitter no longer supports 'lite'
+ $this->lite = $this->arg('lite');
+
+ $this->ids_only = $this->arg('ids_only');
+
+ // If called as a social graph method, show 5000 per page, otherwise 100
+
+ $this->count = isset($this->ids_only) ?
+ 5000 : (int)$this->arg('count', 100);
+
+ $this->user = $this->getTargetUser($this->arg('id'));
+
+ if (empty($this->user)) {
+ $this->clientError(_('No such user!'), 404, $this->format);
+ return false;
+ }
+
+ $this->profiles = $this->getProfiles();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Show the profiles
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (!in_array($this->format, array('xml', 'json'))) {
+ $this->clientError(_('API method not found!'), $code = 404);
+ return;
+ }
+
+ $this->initDocument($this->format);
+
+ if (isset($this->ids_only)) {
+ $this->showIds();
+ } else {
+ $this->showProfiles(isset($this->lite) ? false : true);
+ }
+
+ $this->endDocument($this->format);
+ }
+
+ /**
+ * Get profiles - should get overrrided
+ *
+ * @return array Profiles
+ */
+
+ function getProfiles()
+ {
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this feed last modified?
+ *
+ * @return string datestamp of the latest profile in the stream
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->profiles) && (count($this->profiles) > 0)) {
+ return strtotime($this->profiles[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this action
+ *
+ * Returns an Etag based on the action name, language, user ID, and
+ * timestamps of the first and last profiles in the subscriptions list
+ * There's also an indicator to show whether this action is being called
+ * as /api/statuses/(friends|followers) or /api/(friends|followers)/ids
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->profiles) && (count($this->profiles) > 0)) {
+
+ $last = count($this->profiles) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->user->id,
+ isset($this->ids_only) ? 'IDs' : 'Profiles',
+ strtotime($this->profiles[0]->created),
+ strtotime($this->profiles[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+ /**
+ * Show the profiles as Twitter-style useres and statuses
+ *
+ * @param boolean $include_statuses Whether to include the latest status
+ * with each user. Default true.
+ *
+ * @return void
+ */
+
+ function showProfiles($include_statuses = true)
+ {
+ switch ($this->format) {
+ case 'xml':
+ $this->elementStart('users', array('type' => 'array'));
+ foreach ($this->profiles as $profile) {
+ $this->showProfile(
+ $profile,
+ $this->format,
+ null,
+ $include_statuses
+ );
+ }
+ $this->elementEnd('users');
+ break;
+ case 'json':
+ $arrays = array();
+ foreach ($this->profiles as $profile) {
+ $arrays[] = $this->twitterUserArray(
+ $profile,
+ $include_statuses
+ );
+ }
+ print json_encode($arrays);
+ break;
+ default:
+ $this->clientError(_('Unsupported format.'));
+ break;
+ }
+ }
+
+ /**
+ * Show the IDs of the profiles only. 5000 per page. To support
+ * the 'social graph' methods: /api/(friends|followers)/ids
+ *
+ * @return void
+ */
+
+ function showIds()
+ {
+ switch ($this->format) {
+ case 'xml':
+ $this->elementStart('ids');
+ foreach ($this->profiles as $profile) {
+ $this->element('id', null, $profile->id);
+ }
+ $this->elementEnd('ids');
+ break;
+ case 'json':
+ $ids = array();
+ foreach ($this->profiles as $profile) {
+ $ids[] = (int)$profile->id;
+ }
+ print json_encode($ids);
+ break;
+ default:
+ $this->clientError(_('Unsupported format.'));
+ break;
+ }
+ }
+
+}
diff --git a/actions/apitimelinefavorites.php b/actions/apitimelinefavorites.php
new file mode 100644
index 000000000..b8ae74f13
--- /dev/null
+++ b/actions/apitimelinefavorites.php
@@ -0,0 +1,237 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a user's favorite notices
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net> * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/lib/apibareauth.php';
+
+/**
+ * Returns the 20 most recent favorite notices for the authenticating user or user
+ * specified by the ID parameter in the requested format.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiTimelineFavoritesAction extends ApiBareAuthAction
+{
+ var $notices = null;
+
+ /**
+ * 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;
+ }
+
+ $this->notices = $this->getNotices();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Just show the notices
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showTimeline();
+ }
+
+ /**
+ * Show the timeline of notices
+ *
+ * @return void
+ */
+
+ function showTimeline()
+ {
+ $profile = $this->user->getProfile();
+
+ $sitename = common_config('site', 'name');
+ $title = sprintf(
+ _('%s / Favorites from %s'),
+ $sitename,
+ $this->user->nickname
+ );
+
+ $taguribase = common_config('integration', 'taguri');
+ $id = "tag:$taguribase:Favorites:" . $this->user->id;
+ $link = common_local_url(
+ 'favorites',
+ array('nickname' => $this->user->nickname)
+ );
+ $subtitle = sprintf(
+ _('%s updates favorited by %s / %s.'),
+ $sitename,
+ $profile->getBestName(),
+ $this->user->nickname
+ );
+
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlTimeline($this->notices);
+ break;
+ case 'rss':
+ $this->showRssTimeline($this->notices, $title, $link, $subtitle);
+ break;
+ case 'atom':
+ $selfuri = common_root_url() .
+ ltrim($_SERVER['QUERY_STRING'], 'p=');
+ $this->showAtomTimeline(
+ $this->notices, $title, $id, $link, $subtitle,
+ null, $selfuri
+ );
+ break;
+ case 'json':
+ $this->showJsonTimeline($this->notices);
+ break;
+ default:
+ $this->clientError(_('API method not found!'), $code = 404);
+ break;
+ }
+ }
+
+ /**
+ * Get notices
+ *
+ * @return array notices
+ */
+
+ function getNotices()
+ {
+ $notices = array();
+
+ if (!empty($this->auth_user) && $this->auth_user->id == $this->user->id) {
+ $notice = $this->user->favoriteNotices(
+ ($this->page-1) * $this->count,
+ $this->count,
+ true
+ );
+ } else {
+ $notice = $this->user->favoriteNotices(
+ ($this->page-1) * $this->count,
+ $this->count,
+ false
+ );
+ }
+
+ while ($notice->fetch()) {
+ $notices[] = clone($notice);
+ }
+
+ return $notices;
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this feed last modified?
+ *
+ * @return string datestamp of the latest notice in the stream
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+ return strtotime($this->notices[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this stream
+ *
+ * Returns an Etag based on the action name, language, user ID, and
+ * timestamps of the first and last notice in the timeline
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+
+ $last = count($this->notices) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->user->id,
+ strtotime($this->notices[0]->created),
+ strtotime($this->notices[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apitimelinefriends.php b/actions/apitimelinefriends.php
new file mode 100644
index 000000000..1ea35866e
--- /dev/null
+++ b/actions/apitimelinefriends.php
@@ -0,0 +1,247 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show the friends timeline
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author mac65 <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apibareauth.php';
+
+/**
+ * Returns the most recent notices (default 20) posted by the target user.
+ * This is the equivalent of 'You and friends' page accessed via Web.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author mac65 <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiTimelineFriendsAction extends ApiBareAuthAction
+{
+ var $notices = null;
+
+ /**
+ * 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;
+ }
+
+ $this->notices = $this->getNotices();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Just show the notices
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showTimeline();
+ }
+
+ /**
+ * Show the timeline of notices
+ *
+ * @return void
+ */
+
+ function showTimeline()
+ {
+ $profile = $this->user->getProfile();
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_("%s and friends"), $this->user->nickname);
+ $taguribase = common_config('integration', 'taguri');
+ $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
+ );
+
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlTimeline($this->notices);
+ break;
+ case 'rss':
+ $this->showRssTimeline($this->notices, $title, $link, $subtitle);
+ break;
+ case 'atom':
+
+ $target_id = $this->arg('id');
+
+ 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';
+ }
+
+ $this->showAtomTimeline(
+ $this->notices, $title, $id, $link,
+ $subtitle, null, $selfuri
+ );
+ break;
+ case 'json':
+ $this->showJsonTimeline($this->notices);
+ break;
+ default:
+ $this->clientError(_('API method not found!'), $code = 404);
+ break;
+ }
+ }
+
+ /**
+ * Get notices
+ *
+ * @return array notices
+ */
+
+ function getNotices()
+ {
+ $notices = array();
+
+ if (!empty($this->auth_user) && $this->auth_user->id == $this->user->id) {
+ $notice = $this->user->noticeInbox(
+ ($this->page-1) * $this->count,
+ $this->count, $this->since_id,
+ $this->max_id, $this->since
+ );
+ } else {
+ $notice = $this->user->noticesWithFriends(
+ ($this->page-1) * $this->count,
+ $this->count, $this->since_id,
+ $this->max_id, $this->since
+ );
+ }
+
+ while ($notice->fetch()) {
+ $notices[] = clone($notice);
+ }
+
+ return $notices;
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this feed last modified?
+ *
+ * @return string datestamp of the latest notice in the stream
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+ return strtotime($this->notices[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this stream
+ *
+ * Returns an Etag based on the action name, language, user ID, and
+ * timestamps of the first and last notice in the timeline
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+
+ $last = count($this->notices) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->user->id,
+ strtotime($this->notices[0]->created),
+ strtotime($this->notices[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apitimelinegroup.php b/actions/apitimelinegroup.php
new file mode 100644
index 000000000..5d0542918
--- /dev/null
+++ b/actions/apitimelinegroup.php
@@ -0,0 +1,231 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a group's notices
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/api.php';
+
+/**
+ * Returns the most recent notices (default 20) posted to the group specified by ID
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiTimelineGroupAction extends ApiAction
+{
+
+ var $group = null;
+ var $notices = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->group = $this->getTargetGroup($this->arg('id'));
+ $this->notices = $this->getNotices();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Just show the notices
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showTimeline();
+ }
+
+ /**
+ * Show the timeline of notices
+ *
+ * @return void
+ */
+
+ function showTimeline()
+ {
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_("%s timeline"), $this->group->nickname);
+ $taguribase = common_config('integration', 'taguri');
+ $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
+ );
+
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlTimeline($this->notices);
+ break;
+ case 'rss':
+ $this->showRssTimeline($this->notices, $title, $link, $subtitle);
+ break;
+ case 'atom':
+ $selfuri = common_root_url() .
+ 'api/statusnet/groups/timeline/' .
+ $this->group->nickname . '.atom';
+ $this->showAtomTimeline(
+ $this->notices,
+ $title,
+ $id,
+ $link,
+ $subtitle,
+ null,
+ $selfuri
+ );
+ break;
+ case 'json':
+ $this->showJsonTimeline($this->notices);
+ break;
+ default:
+ $this->clientError(
+ _('API method not found!'),
+ 404,
+ $this->format
+ );
+ break;
+ }
+ }
+
+ /**
+ * Get notices
+ *
+ * @return array notices
+ */
+
+ function getNotices()
+ {
+ $notices = array();
+
+ $notice = $this->group->getNotices(
+ ($this->page-1) * $this->count,
+ $this->count,
+ $this->since_id,
+ $this->max_id,
+ $this->since
+ );
+
+ while ($notice->fetch()) {
+ $notices[] = clone($notice);
+ }
+
+ return $notices;
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this feed last modified?
+ *
+ * @return string datestamp of the latest notice in the stream
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+ return strtotime($this->notices[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this stream
+ *
+ * Returns an Etag based on the action name, language, group ID and
+ * timestamps of the first and last notice in the timeline
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+
+ $last = count($this->notices) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->group->id,
+ strtotime($this->notices[0]->created),
+ strtotime($this->notices[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apitimelinementions.php b/actions/apitimelinementions.php
new file mode 100644
index 000000000..fe5ff0f28
--- /dev/null
+++ b/actions/apitimelinementions.php
@@ -0,0 +1,233 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show notices mentioning a user (@nickname)
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author mac65 <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apibareauth.php';
+
+/**
+ * Returns the most recent (default 20) mentions (status containing @nickname)
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author mac65 <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiTimelineMentionsAction extends ApiBareAuthAction
+{
+
+ var $notices = null;
+
+ /**
+ * 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;
+ }
+
+ $this->notices = $this->getNotices();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Just show the notices
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showTimeline();
+ }
+
+ /**
+ * Show the timeline of notices
+ *
+ * @return void
+ */
+
+ function showTimeline()
+ {
+ $profile = $this->user->getProfile();
+
+ $sitename = common_config('site', 'name');
+ $title = sprintf(
+ _('%1$s / Updates mentioning %2$s'),
+ $sitename, $this->user->nickname
+ );
+ $taguribase = common_config('integration', 'taguri');
+ $id = "tag:$taguribase:Mentions:" . $this->user->id;
+ $link = common_local_url(
+ 'replies',
+ array('nickname' => $this->user->nickname)
+ );
+ $subtitle = sprintf(
+ _('%1$s updates that reply to updates from %2$s / %3$s.'),
+ $sitename, $this->user->nickname, $profile->getBestName()
+ );
+
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlTimeline($this->notices);
+ break;
+ case 'rss':
+ $this->showRssTimeline($this->notices, $title, $link, $subtitle);
+ break;
+ case 'atom':
+ $selfuri = common_root_url() .
+ ltrim($_SERVER['QUERY_STRING'], 'p=');
+ $this->showAtomTimeline(
+ $this->notices, $title, $id, $link, $subtitle,
+ null, $selfuri
+ );
+ break;
+ case 'json':
+ $this->showJsonTimeline($this->notices);
+ break;
+ default:
+ $this->clientError(_('API method not found!'), $code = 404);
+ break;
+ }
+ }
+
+ /**
+ * Get notices
+ *
+ * @return array notices
+ */
+
+ function getNotices()
+ {
+ $notices = array();
+
+ $notice = $this->user->getReplies(
+ ($this->page - 1) * $this->count, $this->count,
+ $this->since_id, $this->max_id, $this->since
+ );
+
+ while ($notice->fetch()) {
+ $notices[] = clone($notice);
+ }
+
+ return $notices;
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this feed last modified?
+ *
+ * @return string datestamp of the latest notice in the stream
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+ return strtotime($this->notices[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this stream
+ *
+ * Returns an Etag based on the action name, language, user ID, and
+ * timestamps of the first and last notice in the timeline
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+
+ $last = count($this->notices) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->user->id,
+ strtotime($this->notices[0]->created),
+ strtotime($this->notices[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apitimelinepublic.php b/actions/apitimelinepublic.php
new file mode 100644
index 000000000..58e267734
--- /dev/null
+++ b/actions/apitimelinepublic.php
@@ -0,0 +1,213 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show the public timeline
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author mac65 <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/api.php';
+
+/**
+ * Returns the most recent notices (default 20) posted by everybody
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author mac65 <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiTimelinePublicAction extends ApiAction
+{
+
+ var $notices = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->notices = $this->getNotices();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Just show the notices
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showTimeline();
+ }
+
+ /**
+ * Show the timeline of notices
+ *
+ * @return void
+ */
+
+ function showTimeline()
+ {
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_("%s public timeline"), $sitename);
+ $taguribase = common_config('integration', 'taguri');
+ $id = "tag:$taguribase:PublicTimeline";
+ $link = common_root_url();
+ $subtitle = sprintf(_("%s updates from everyone!"), $sitename);
+
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlTimeline($this->notices);
+ break;
+ case 'rss':
+ $this->showRssTimeline($this->notices, $title, $link, $subtitle);
+ break;
+ case 'atom':
+ $selfuri = common_root_url() . 'api/statuses/public_timeline.atom';
+ $this->showAtomTimeline(
+ $this->notices, $title, $id, $link,
+ $subtitle, null, $selfuri
+ );
+ break;
+ case 'json':
+ $this->showJsonTimeline($this->notices);
+ break;
+ default:
+ $this->clientError(_('API method not found!'), $code = 404);
+ break;
+ }
+ }
+
+ /**
+ * Get notices
+ *
+ * @return array notices
+ */
+
+ function getNotices()
+ {
+ $notices = array();
+
+ $notice = Notice::publicStream(
+ ($this->page - 1) * $this->count, $this->count, $this->since_id,
+ $this->max_id, $this->since
+ );
+
+ while ($notice->fetch()) {
+ $notices[] = clone($notice);
+ }
+
+ return $notices;
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this feed last modified?
+ *
+ * @return string datestamp of the latest notice in the stream
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+ return strtotime($this->notices[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this stream
+ *
+ * Returns an Etag based on the action name, language, and
+ * timestamps of the first and last notice in the timeline
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+
+ $last = count($this->notices) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ strtotime($this->notices[0]->created),
+ strtotime($this->notices[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apitimelinetag.php b/actions/apitimelinetag.php
new file mode 100644
index 000000000..a274daac0
--- /dev/null
+++ b/actions/apitimelinetag.php
@@ -0,0 +1,224 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show the latest notices for a given tag
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/api.php';
+
+/**
+ * Returns the 20 most recent notices tagged by a given tag
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiTimelineTagAction extends ApiAction
+{
+
+ var $notices = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->tag = $this->arg('tag');
+ $this->notices = $this->getNotices();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Just show the notices
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showTimeline();
+ }
+
+ /**
+ * Show the timeline of notices
+ *
+ * @return void
+ */
+
+ function showTimeline()
+ {
+ $sitename = common_config('site', 'name');
+ $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');
+ $id = "tag:$taguribase:TagTimeline:".$tag;
+
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlTimeline($this->notices);
+ break;
+ case 'rss':
+ $this->showRssTimeline($this->notices, $title, $link, $subtitle);
+ break;
+ case 'atom':
+ $selfuri = common_root_url() .
+ 'api/statusnet/tags/timeline/' .
+ $this->tag . '.atom';
+ $this->showAtomTimeline(
+ $this->notices,
+ $title,
+ $id,
+ $link,
+ $subtitle,
+ null,
+ $selfuri
+ );
+ break;
+ case 'json':
+ $this->showJsonTimeline($this->notices);
+ break;
+ default:
+ $this->clientError(_('API method not found!'), $code = 404);
+ break;
+ }
+ }
+
+ /**
+ * Get notices
+ *
+ * @return array notices
+ */
+
+ function getNotices()
+ {
+ $notices = array();
+
+ $notice = Notice_tag::getStream(
+ $this->tag,
+ ($this->page - 1) * $this->count,
+ $this->count + 1
+ );
+
+ while ($notice->fetch()) {
+ $notices[] = clone($notice);
+ }
+
+ return $notices;
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this feed last modified?
+ *
+ * @return string datestamp of the latest notice in the stream
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+ return strtotime($this->notices[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this stream
+ *
+ * Returns an Etag based on the action name, language, and
+ * timestamps of the first and last notice in the timeline
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+
+ $last = count($this->notices) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->tag,
+ strtotime($this->notices[0]->created),
+ strtotime($this->notices[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php
new file mode 100644
index 000000000..285735fd1
--- /dev/null
+++ b/actions/apitimelineuser.php
@@ -0,0 +1,248 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a user's timeline
+ *
+ * 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 Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author mac65 <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apibareauth.php';
+
+/**
+ * Returns the most recent notices (default 20) posted by the authenticating
+ * user. Another user's timeline can be requested via the id parameter. This
+ * is the API equivalent of the user profile web page.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Jeffery To <jeffery.to@gmail.com>
+ * @author mac65 <mac65@mac65.com>
+ * @author Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiTimelineUserAction extends ApiBareAuthAction
+{
+
+ var $notices = null;
+
+ /**
+ * 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;
+ }
+
+ $this->notices = $this->getNotices();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Just show the notices
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showTimeline();
+ }
+
+ /**
+ * Show the timeline of notices
+ *
+ * @return void
+ */
+
+ function showTimeline()
+ {
+ $profile = $this->user->getProfile();
+
+ $sitename = common_config('site', 'name');
+ $title = sprintf(_("%s timeline"), $this->user->nickname);
+ $taguribase = common_config('integration', 'taguri');
+ $id = "tag:$taguribase:UserTimeline:" . $this->user->id;
+ $link = common_local_url(
+ 'showstream',
+ array('nickname' => $this->user->nickname)
+ );
+ $subtitle = sprintf(
+ _('Updates from %1$s on %2$s!'),
+ $this->user->nickname, $sitename
+ );
+
+ // FriendFeed's SUP protocol
+ // Also added RSS and Atom feeds
+
+ $suplink = common_local_url('sup', null, null, $this->user->id);
+ header('X-SUP-ID: ' . $suplink);
+
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlTimeline($this->notices);
+ break;
+ case 'rss':
+ $this->showRssTimeline(
+ $this->notices, $title, $link,
+ $subtitle, $suplink
+ );
+ break;
+ case 'atom':
+ if (isset($apidata['api_arg'])) {
+ $selfuri = common_root_url() .
+ 'api/statuses/user_timeline/' .
+ $apidata['api_arg'] . '.atom';
+ } else {
+ $selfuri = common_root_url() .
+ 'api/statuses/user_timeline.atom';
+ }
+ $this->showAtomTimeline(
+ $this->notices, $title, $id, $link,
+ $subtitle, $suplink, $selfuri
+ );
+ break;
+ case 'json':
+ $this->showJsonTimeline($this->notices);
+ break;
+ default:
+ $this->clientError(_('API method not found!'), $code = 404);
+ break;
+ }
+
+ }
+
+ /**
+ * Get notices
+ *
+ * @return array notices
+ */
+
+ function getNotices()
+ {
+ $notices = array();
+
+ $notice = $this->user->getNotices(
+ ($this->page-1) * $this->count, $this->count,
+ $this->since_id, $this->max_id, $this->since
+ );
+
+ while ($notice->fetch()) {
+ $notices[] = clone($notice);
+ }
+
+ return $notices;
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this feed last modified?
+ *
+ * @return string datestamp of the latest notice in the stream
+ */
+
+ function lastModified()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+ return strtotime($this->notices[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * An entity tag for this stream
+ *
+ * Returns an Etag based on the action name, language, user ID, and
+ * timestamps of the first and last notice in the timeline
+ *
+ * @return string etag
+ */
+
+ function etag()
+ {
+ if (!empty($this->notices) && (count($this->notices) > 0)) {
+
+ $last = count($this->notices) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_language(),
+ $this->user->id,
+ strtotime($this->notices[0]->created),
+ strtotime($this->notices[$last]->created))
+ )
+ . '"';
+ }
+
+ return null;
+ }
+
+}
diff --git a/actions/apiuserfollowers.php b/actions/apiuserfollowers.php
new file mode 100644
index 000000000..e8d92a773
--- /dev/null
+++ b/actions/apiuserfollowers.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a user's followers (subscribers)
+ *
+ * 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 Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apibareauth.php';
+
+/**
+ * Ouputs the authenticating user's followers (subscribers), each with
+ * current Twitter-style status inline. They are ordered by the order
+ * in which they subscribed to the user, 100 at a time.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiUserFollowersAction extends ApiSubscriptionsAction
+{
+ /**
+ * Get the user's subscribers (followers) as an array of profiles
+ *
+ * @return array Profiles
+ */
+
+ function getProfiles()
+ {
+ $offset = ($this->page - 1) * $this->count;
+ $limit = $this->count + 1;
+
+ $subs = null;
+
+ if (isset($this->tag)) {
+ $subs = $this->user->getTaggedSubscribers(
+ $this->tag, $offset, $limit
+ );
+ } else {
+ $subs = $this->user->getSubscribers(
+ $offset,
+ $limit
+ );
+ }
+
+ $profiles = array();
+
+ if (!empty($subs)) {
+ while ($subs->fetch()) {
+ $profiles[] = clone($subs);
+ }
+ }
+
+ return $profiles;
+ }
+
+}
diff --git a/actions/apiuserfriends.php b/actions/apiuserfriends.php
new file mode 100644
index 000000000..741a26e58
--- /dev/null
+++ b/actions/apiuserfriends.php
@@ -0,0 +1,89 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a user's friends (subscriptions)
+ *
+ * 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 Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/apibareauth.php';
+
+/**
+ * Ouputs the authenticating user's friends (subscriptions), each with
+ * current Twitter-style status inline. They are ordered by the date
+ * in which the user subscribed to them, 100 at a time.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiUserFriendsAction extends ApiSubscriptionsAction
+{
+ /**
+ * Get the user's subscriptions (friends) as an array of profiles
+ *
+ * @return array Profiles
+ */
+
+ function getProfiles()
+ {
+ $offset = ($this->page - 1) * $this->count;
+ $limit = $this->count + 1;
+
+ $subs = null;
+
+ if (isset($this->tag)) {
+ $subs = $this->user->getTaggedSubscriptions(
+ $this->tag, $offset, $limit
+ );
+ } else {
+ $subs = $this->user->getSubscriptions(
+ $offset,
+ $limit
+ );
+ }
+
+ $profiles = array();
+
+ if (!empty($subs)) {
+ while ($subs->fetch()) {
+ $profiles[] = clone($subs);
+ }
+ }
+
+ return $profiles;
+ }
+
+}
diff --git a/actions/apiusershow.php b/actions/apiusershow.php
new file mode 100644
index 000000000..b3a939b43
--- /dev/null
+++ b/actions/apiusershow.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a user's profile information
+ *
+ * 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 Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author mac65 <mac65@mac65.com>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+require_once INSTALLDIR . '/lib/api.php';
+
+/**
+ * Ouputs information for a user, specified by ID or screen name.
+ * The user's most recent status will be returned inline.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Dan Moore <dan@moore.cx>
+ * @author Evan Prodromou <evan@status.net>
+ * @author mac65 <mac65@mac65.com>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ApiUserShowAction extends ApiAction
+{
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ *
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $email = $this->arg('email');
+
+ // XXX: email field deprecated in Twitter's API
+
+ if (!empty($email)) {
+ $this->user = User::staticGet('email', $email);
+ } else {
+ $this->user = $this->getTargetUser($this->arg('id'));
+ }
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Check the format and show the user info
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (empty($this->user)) {
+ $this->clientError(_('Not found.'), 404, $this->format);
+ return;
+ }
+
+ if (!in_array($this->format, array('xml', 'json'))) {
+ $this->clientError(_('API method not found!'), $code = 404);
+ return;
+ }
+
+ $profile = $this->user->getProfile();
+
+ if (empty($profile)) {
+ $this->clientError(_('User has no profile.'));
+ return;
+ }
+
+ $twitter_user = $this->twitterUserArray($this->user->getProfile(), true);
+
+ if ($this->format == 'xml') {
+ $this->initDocument('xml');
+ $this->showTwitterXmlUser($twitter_user);
+ $this->endDocument('xml');
+ } elseif ($this->format == 'json') {
+ $this->initDocument('json');
+ $this->showJsonObjects($twitter_user);
+ $this->endDocument('json');
+ }
+
+ }
+
+}
diff --git a/actions/avatarsettings.php b/actions/avatarsettings.php
index 02a684b38..ded419dd7 100644
--- a/actions/avatarsettings.php
+++ b/actions/avatarsettings.php
@@ -362,13 +362,13 @@ class AvatarsettingsAction extends AccountSettingsAction
$profile = $user->getProfile();
$avatar = $profile->getOriginalAvatar();
- $avatar->delete();
+ if($avatar) $avatar->delete();
$avatar = $profile->getAvatar(AVATAR_PROFILE_SIZE);
- $avatar->delete();
+ if($avatar) $avatar->delete();
$avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
- $avatar->delete();
+ if($avatar) $avatar->delete();
$avatar = $profile->getAvatar(AVATAR_MINI_SIZE);
- $avatar->delete();
+ if($avatar) $avatar->delete();
$this->showForm(_('Avatar deleted.'), true);
}
diff --git a/actions/deletenotice.php b/actions/deletenotice.php
index 3d040f2fa..4a48a9c34 100644
--- a/actions/deletenotice.php
+++ b/actions/deletenotice.php
@@ -32,15 +32,45 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
-require_once INSTALLDIR.'/lib/deleteaction.php';
-
-class DeletenoticeAction extends DeleteAction
+class DeletenoticeAction extends Action
{
- var $error = null;
+ var $error = null;
+ var $user = null;
+ var $notice = null;
+ var $profile = null;
+ var $user_profile = null;
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = common_current_user();
+ $notice_id = $this->trimmed('notice');
+ $this->notice = Notice::staticGet($notice_id);
+
+ if (!$this->notice) {
+ common_user_error(_('No such notice.'));
+ exit;
+ }
+
+ $this->profile = $this->notice->getProfile();
+ $this->user_profile = $this->user->getProfile();
+
+ return true;
+ }
function handle($args)
{
parent::handle($args);
+
+ if (!common_logged_in()) {
+ common_user_error(_('Not logged in.'));
+ exit;
+ } else if ($this->notice->profile_id != $this->user_profile->id &&
+ !$this->user->hasRight(Right::deleteOthersNotice)) {
+ common_user_error(_('Can\'t delete this notice.'));
+ exit;
+ }
// XXX: Ajax!
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
diff --git a/actions/editgroup.php b/actions/editgroup.php
index 0c2dc8bdf..5dd039f8a 100644
--- a/actions/editgroup.php
+++ b/actions/editgroup.php
@@ -250,7 +250,6 @@ class EditgroupAction extends GroupDesignAction
$this->group->homepage = $homepage;
$this->group->description = $description;
$this->group->location = $location;
- $this->group->created = common_sql_now();
$result = $this->group->update($orig);
diff --git a/actions/favoritesrss.php b/actions/favoritesrss.php
index 2d5ce9854..62f06e841 100644
--- a/actions/favoritesrss.php
+++ b/actions/favoritesrss.php
@@ -50,11 +50,11 @@ require_once INSTALLDIR.'/lib/rssaction.php';
*/
class FavoritesrssAction extends Rss10Action
{
-
+
/** The user whose favorites to display */
-
+
var $user = null;
-
+
/**
* Find the user to display by supplied nickname
*
@@ -66,7 +66,7 @@ class FavoritesrssAction extends Rss10Action
function prepare($args)
{
parent::prepare($args);
-
+
$nickname = $this->trimmed('nickname');
$this->user = User::staticGet('nickname', $nickname);
@@ -74,10 +74,11 @@ class FavoritesrssAction extends Rss10Action
$this->clientError(_('No such user.'));
return false;
} else {
+ $this->notices = $this->getNotices($this->limit);
return true;
}
}
-
+
/**
* Get notices
*
diff --git a/actions/finishremotesubscribe.php b/actions/finishremotesubscribe.php
index 5f6807d10..b1cec66f4 100644
--- a/actions/finishremotesubscribe.php
+++ b/actions/finishremotesubscribe.php
@@ -143,67 +143,4 @@ class FinishremotesubscribeAction extends Action
$user->nickname)),
303);
}
-
- function add_avatar($profile, $url)
- {
- $temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
- copy($url, $temp_filename);
- $imagefile = new ImageFile($profile->id, $temp_filename);
- $filename = Avatar::filename($profile->id,
- image_type_to_extension($imagefile->type),
- null,
- common_timestamp());
- rename($temp_filename, Avatar::path($filename));
- return $profile->setOriginal($filename);
- }
-
- function access_token($omb)
- {
-
- common_debug('starting request for access token', __FILE__);
-
- $con = omb_oauth_consumer();
- $tok = new OAuthToken($omb['token'], $omb['secret']);
-
- common_debug('using request token "'.$tok.'"', __FILE__);
-
- $url = $omb['access_token_url'];
-
- common_debug('using access token url "'.$url.'"', __FILE__);
-
- # XXX: Is this the right thing to do? Strip off GET params and make them
- # POST params? Seems wrong to me.
-
- $parsed = parse_url($url);
- $params = array();
- parse_str($parsed['query'], $params);
-
- $req = OAuthRequest::from_consumer_and_token($con, $tok, "POST", $url, $params);
-
- $req->set_parameter('omb_version', OMB_VERSION_01);
-
- # XXX: test to see if endpoint accepts this signature method
-
- $req->sign_request(omb_hmac_sha1(), $con, $tok);
-
- # We re-use this tool's fetcher, since it's pretty good
-
- common_debug('posting to access token url "'.$req->get_normalized_http_url().'"', __FILE__);
- common_debug('posting request data "'.$req->to_postdata().'"', __FILE__);
-
- $fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
- $result = $fetcher->post($req->get_normalized_http_url(),
- $req->to_postdata(),
- array('User-Agent: StatusNet/' . STATUSNET_VERSION));
-
- common_debug('got result: "'.print_r($result,true).'"', __FILE__);
-
- if ($result->status != 200) {
- return null;
- }
-
- parse_str($result->body, $return);
-
- return array($return['oauth_token'], $return['oauth_token_secret']);
- }
}
diff --git a/actions/foafgroup.php b/actions/foafgroup.php
new file mode 100644
index 000000000..f5fd7fe88
--- /dev/null
+++ b/actions/foafgroup.php
@@ -0,0 +1,173 @@
+<?php
+/*
+ * StatusNet the 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/>.
+ *
+ * @category Mail
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Toby Inkster <mail@tobyinkster.co.uk>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
+
+class FoafGroupAction extends Action
+{
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $nickname_arg = $this->arg('nickname');
+
+ if (empty($nickname_arg)) {
+ $this->clientError(_('No such group.'), 404);
+ return false;
+ }
+
+ $this->nickname = common_canonical_nickname($nickname_arg);
+
+ // Permanent redirect on non-canonical nickname
+
+ if ($nickname_arg != $this->nickname) {
+ common_redirect(common_local_url('foafgroup',
+ array('nickname' => $this->nickname)),
+ 301);
+ return false;
+ }
+
+ $this->group = User_group::staticGet('nickname', $this->nickname);
+
+ if (!$this->group) {
+ $this->clientError(_('No such group.'), 404);
+ return false;
+ }
+
+ common_set_returnto($this->selfUrl());
+
+ return true;
+ }
+
+ function handle($args)
+ {
+ parent::handle($args);
+
+ header('Content-Type: application/rdf+xml');
+
+ $this->startXML();
+ $this->elementStart('rdf:RDF', array('xmlns:rdf' =>
+ 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
+ 'xmlns:dcterms' =>
+ 'http://purl.org/dc/terms/',
+ 'xmlns:sioc' =>
+ 'http://rdfs.org/sioc/ns#',
+ 'xmlns:foaf' =>
+ 'http://xmlns.com/foaf/0.1/',
+ 'xmlns:statusnet' =>
+ 'http://status.net/ont/',
+ 'xmlns' => 'http://xmlns.com/foaf/0.1/'));
+
+ $this->showPpd(common_local_url('foafgroup', array('nickname' => $this->nickname)), $this->group->permalink());
+
+ $this->elementStart('Group', array('rdf:about' =>
+ $this->group->permalink()));
+ if ($this->group->fullname) {
+ $this->element('name', null, $this->group->fullname);
+ }
+ if ($this->group->description) {
+ $this->element('dcterms:description', null, $this->group->description);
+ }
+ if ($this->group->nickname) {
+ $this->element('dcterms:identifier', null, $this->group->nickname);
+ $this->element('nick', null, $this->group->nickname);
+ }
+ foreach ($this->group->getAliases() as $alias) {
+ $this->element('nick', null, $alias);
+ }
+ if ($this->group->homeUrl()) {
+ $this->element('weblog', array('rdf:resource' => $this->group->homeUrl()));
+ }
+ if ($this->group->homepage) {
+ $this->element('page', array('rdf:resource' => $this->group->homepage));
+ }
+ if ($this->group->homepage_logo) {
+ $this->element('depiction', array('rdf:resource' => $this->group->homepage_logo));
+ }
+
+ $members = $this->group->getMembers();
+ $member_details = array();
+ while ($members->fetch()) {
+ $member_uri = common_local_url('userbyid', array('id'=>$members->id));
+ $member_details[$member_uri] = array(
+ 'nickname' => $members->nickname
+ );
+ $this->element('member', array('rdf:resource' => $member_uri));
+ }
+
+ $admins = $this->group->getAdmins();
+ while ($admins->fetch()) {
+ $admin_uri = common_local_url('userbyid', array('id'=>$admins->id));
+ $member_details[$admin_uri]['is_admin'] = true;
+ $this->element('statusnet:groupAdmin', array('rdf:resource' => $admin_uri));
+ }
+
+ $this->elementEnd('Group');
+
+ ksort($member_details);
+ foreach ($member_details as $uri => $details) {
+ if ($details['is_admin'])
+ {
+ $this->elementStart('Agent', array('rdf:about' => $uri));
+ $this->element('nick', null, $details['nickname']);
+ $this->elementStart('holdsAccount');
+ $this->elementStart('sioc:User', array('rdf:about'=>$uri.'#acct'));
+ $this->elementStart('sioc:has_function');
+ $this->elementStart('statusnet:GroupAdminRole');
+ $this->element('sioc:scope', array('rdf:resource' => $this->group->permalink()));
+ $this->elementEnd('statusnet:GroupAdminRole');
+ $this->elementEnd('sioc:has_function');
+ $this->elementEnd('sioc:User');
+ $this->elementEnd('holdsAccount');
+ $this->elementEnd('Agent');
+ }
+ else
+ {
+ $this->element('Agent', array(
+ 'foaf:nick' => $details['nickname'],
+ 'rdf:about' => $uri,
+ ));
+ }
+ }
+
+ $this->elementEnd('rdf:RDF');
+ $this->endXML();
+ }
+
+ function showPpd($foaf_url, $person_uri)
+ {
+ $this->elementStart('Document', array('rdf:about' => $foaf_url));
+ $this->element('primaryTopic', array('rdf:resource' => $person_uri));
+ $this->elementEnd('Document');
+ }
+
+} \ No newline at end of file
diff --git a/actions/grouprss.php b/actions/grouprss.php
index 70c1ded48..6a6b55e78 100644
--- a/actions/grouprss.php
+++ b/actions/grouprss.php
@@ -104,6 +104,7 @@ class groupRssAction extends Rss10Action
return false;
}
+ $this->notices = $this->getNotices($this->limit);
return true;
}
diff --git a/actions/groupsearch.php b/actions/groupsearch.php
index f0cca7156..55f4cee62 100644
--- a/actions/groupsearch.php
+++ b/actions/groupsearch.php
@@ -105,7 +105,7 @@ class GroupSearchResults extends GroupList
function __construct($user_group, $terms, $action)
{
- parent::__construct($user_group, $terms, $action);
+ parent::__construct($user_group, null, $action);
$this->terms = array_map('preg_quote',
array_map('htmlspecialchars', $terms));
$this->pattern = '/('.implode('|',$terms).')/i';
diff --git a/actions/newnotice.php b/actions/newnotice.php
index 4c6372c2b..d5b0332f4 100644
--- a/actions/newnotice.php
+++ b/actions/newnotice.php
@@ -255,13 +255,6 @@ class NewnoticeAction extends Action
$notice = Notice::saveNew($user->id, $content_shortened, 'web', 1,
($replyto == 'false') ? null : $replyto);
- if (is_string($notice)) {
- if (isset($filename)) {
- $this->deleteFile($filename);
- }
- $this->clientError($notice);
- }
-
if (isset($mimetype)) {
$this->attachFile($notice, $fileRecord);
}
@@ -433,13 +426,14 @@ class NewnoticeAction extends Action
$content = $this->trimmed('status_textarea');
if (!$content) {
$replyto = $this->trimmed('replyto');
+ $inreplyto = $this->trimmed('inreplyto');
$profile = Profile::staticGet('nickname', $replyto);
if ($profile) {
$content = '@' . $profile->nickname . ' ';
}
}
- $notice_form = new NoticeForm($this, '', $content);
+ $notice_form = new NoticeForm($this, '', $content, null, $inreplyto);
$notice_form->show();
}
diff --git a/actions/publicrss.php b/actions/publicrss.php
index 593888b9f..0c5d061cb 100644
--- a/actions/publicrss.php
+++ b/actions/publicrss.php
@@ -50,8 +50,22 @@ require_once INSTALLDIR.'/lib/rssaction.php';
class PublicrssAction extends Rss10Action
{
/**
+ * Read arguments and initialize members
+ *
+ * @param array $args Arguments from $_REQUEST
+ * @return boolean success
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ $this->notices = $this->getNotices($this->limit);
+ return true;
+ }
+
+ /**
* Initialization.
- *
+ *
* @return boolean true
*/
function init()
@@ -73,7 +87,7 @@ class PublicrssAction extends Rss10Action
while ($notice->fetch()) {
$notices[] = clone($notice);
}
-
+
return $notices;
}
diff --git a/actions/repliesrss.php b/actions/repliesrss.php
index c71c9226f..76aae21ad 100644
--- a/actions/repliesrss.php
+++ b/actions/repliesrss.php
@@ -38,6 +38,7 @@ class RepliesrssAction extends Rss10Action
$this->clientError(_('No such user.'));
return false;
} else {
+ $this->notices = $this->getNotices($this->limit);
return true;
}
}
diff --git a/actions/showgroup.php b/actions/showgroup.php
index ff9949762..a67765ce5 100644
--- a/actions/showgroup.php
+++ b/actions/showgroup.php
@@ -345,7 +345,12 @@ class ShowgroupAction extends GroupDesignAction
'method' => 'timeline',
'argument' => $this->group->nickname.'.atom')),
sprintf(_('Notice feed for %s group (Atom)'),
- $this->group->nickname)));
+ $this->group->nickname)),
+ new Feed(Feed::FOAF,
+ common_local_url('foafgroup',
+ array('nickname' => $this->group->nickname)),
+ sprintf(_('FOAF for %s group'),
+ $this->group->nickname)));
}
/**
diff --git a/actions/showstream.php b/actions/showstream.php
index 2e9679fae..cdac4f47b 100644
--- a/actions/showstream.php
+++ b/actions/showstream.php
@@ -378,8 +378,13 @@ class ShowstreamAction extends ProfileAction
$this->showEmptyListMessage();
}
+ $args = array('nickname' => $this->user->nickname);
+ if (!empty($this->tag))
+ {
+ $args['tag'] = $this->tag;
+ }
$this->pagination($this->page>1, $cnt>NOTICES_PER_PAGE, $this->page,
- 'showstream', array('nickname' => $this->user->nickname));
+ 'showstream', $args);
}
function showAnonymousMessage()
diff --git a/actions/twitapiaccount.php b/actions/twitapiaccount.php
deleted file mode 100644
index 93c8443c9..000000000
--- a/actions/twitapiaccount.php
+++ /dev/null
@@ -1,127 +0,0 @@
-<?php
-/*
- * StatusNet - the 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/>.
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once(INSTALLDIR.'/lib/twitterapi.php');
-
-class TwitapiaccountAction extends TwitterapiAction
-{
- function verify_credentials($args, $apidata)
- {
- parent::handle($args);
-
- switch ($apidata['content-type']) {
- case 'xml':
- case 'json':
- $action_obj = new TwitapiusersAction();
- $action_obj->prepare($args);
- call_user_func(array($action_obj, 'show'), $args, $apidata);
- break;
- default:
- header('Content-Type: text/html; charset=utf-8');
- print 'Authorized';
- }
- }
-
- function end_session($args, $apidata)
- {
- parent::handle($args);
- $this->serverError(_('API method under construction.'), $code=501);
- }
-
- function update_location($args, $apidata)
- {
- parent::handle($args);
-
- if ($_SERVER['REQUEST_METHOD'] != 'POST') {
- $this->clientError(_('This method requires a POST.'),
- 400, $apidata['content-type']);
- return;
- }
-
- $location = trim($this->arg('location'));
-
- if (!is_null($location) && mb_strlen($location) > 255) {
-
- // XXX: But Twitter just truncates and runs with it. -- Zach
- $this->clientError(_('That\'s too long. Max notice size is 255 chars.'),
- 406, $apidate['content-type']);
- return;
- }
-
- $user = $apidata['user']; // Always the auth user
- $profile = $user->getProfile();
-
- $orig_profile = clone($profile);
- $profile->location = $location;
-
- $result = $profile->update($orig_profile);
-
- if (empty($result)) {
- common_log_db_error($profile, 'UPDATE', __FILE__);
- $this->serverError(_('Couldn\'t save profile.'));
- return;
- }
-
- common_broadcast_profile($profile);
- $type = $apidata['content-type'];
-
- $this->init_document($type);
- $this->show_profile($profile, $type);
- $this->end_document($type);
- }
-
-
- function update_delivery_device($args, $apidata)
- {
- parent::handle($args);
- $this->serverError(_('API method under construction.'), $code=501);
- }
-
- // We don't have a rate limit, but some clients check this method.
- // It always returns the same thing: 100 hit left.
- function rate_limit_status($args, $apidata)
- {
- parent::handle($args);
-
- $type = $apidata['content-type'];
- $this->init_document($type);
-
- if ($apidata['content-type'] == 'xml') {
- $this->elementStart('hash');
- $this->element('remaining-hits', array('type' => 'integer'), 100);
- $this->element('hourly-limit', array('type' => 'integer'), 100);
- $this->element('reset-time', array('type' => 'datetime'), null);
- $this->element('reset_time_in_seconds', array('type' => 'integer'), 0);
- $this->elementEnd('hash');
- } elseif ($apidata['content-type'] == 'json') {
-
- $out = array('reset_time_in_seconds' => 0,
- 'remaining_hits' => 100,
- 'hourly_limit' => 100,
- 'reset_time' => '');
- print json_encode($out);
- }
-
- $this->end_document($type);
- }
-}
diff --git a/actions/twitapiblocks.php b/actions/twitapiblocks.php
deleted file mode 100644
index ed17946ae..000000000
--- a/actions/twitapiblocks.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-/*
- * StatusNet - the 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/>.
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once(INSTALLDIR.'/lib/twitterapi.php');
-
-class TwitapiblocksAction extends TwitterapiAction
-{
-
- function create($args, $apidata)
- {
-
- parent::handle($args);
-
- $blockee = $this->get_user($apidata['api_arg'], $apidata);
-
- if (empty($blockee)) {
- $this->clientError('Not Found', 404, $apidata['content-type']);
- return;
- }
-
- $user = $apidata['user']; // Always the auth user
-
- if ($user->hasBlocked($blockee) || $user->block($blockee)) {
- $type = $apidata['content-type'];
- $this->init_document($type);
- $this->show_profile($blockee, $type);
- $this->end_document($type);
- } else {
- $this->serverError(_('Block user failed.'));
- }
- }
-
- function destroy($args, $apidata)
- {
- parent::handle($args);
- $blockee = $this->get_user($apidata['api_arg'], $apidata);
-
- if (empty($blockee)) {
- $this->clientError('Not Found', 404, $apidata['content-type']);
- return;
- }
-
- $user = $apidata['user'];
-
- if (!$user->hasBlocked($blockee) || $user->unblock($blockee)) {
- $type = $apidata['content-type'];
- $this->init_document($type);
- $this->show_profile($blockee, $type);
- $this->end_document($type);
- } else {
- $this->serverError(_('Unblock user failed.'));
- }
- }
-} \ No newline at end of file
diff --git a/actions/twitapidirect_messages.php b/actions/twitapidirect_messages.php
deleted file mode 100644
index 08b8f4e9c..000000000
--- a/actions/twitapidirect_messages.php
+++ /dev/null
@@ -1,305 +0,0 @@
-<?php
-/*
- * StatusNet - the 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/>.
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once(INSTALLDIR.'/lib/twitterapi.php');
-
-class Twitapidirect_messagesAction extends TwitterapiAction
-{
-
- function direct_messages($args, $apidata)
- {
- parent::handle($args);
- return $this->show_messages($args, $apidata, 'received');
- }
-
- function sent($args, $apidata)
- {
- parent::handle($args);
- return $this->show_messages($args, $apidata, 'sent');
- }
-
- function show_messages($args, $apidata, $type)
- {
- $user = $apidata['user']; // Always the auth user
-
- $message = new Message();
- $title = null;
- $subtitle = null;
- $link = null;
- $server = common_root_url();
-
- if ($type == 'received') {
- $message->to_profile = $user->id;
- $title = sprintf(_("Direct messages to %s"), $user->nickname);
- $subtitle = sprintf(_("All the direct messages sent to %s"),
- $user->nickname);
- $link = $server . $user->nickname . '/inbox';
- } else {
- $message->from_profile = $user->id;
- $title = _('Direct Messages You\'ve Sent');
- $subtitle = sprintf(_("All the direct messages sent from %s"),
- $user->nickname);
- $link = $server . $user->nickname . '/outbox';
- }
-
- $page = (int)$this->arg('page', 1);
- $count = (int)$this->arg('count', 20);
- $max_id = (int)$this->arg('max_id', 0);
- $since_id = (int)$this->arg('since_id', 0);
- $since = $this->arg('since');
-
- if ($max_id) {
- $message->whereAdd("id <= $max_id");
- }
-
- if ($since_id) {
- $message->whereAdd("id > $since_id");
- }
-
- if ($since) {
- $d = date('Y-m-d H:i:s', $since);
- $message->whereAdd("created > '$d'");
- }
-
- $message->orderBy('created DESC, id DESC');
- $message->limit((($page-1)*$count), $count);
- $message->find();
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_xml_dmsgs($message);
- break;
- case 'rss':
- $this->show_rss_dmsgs($message, $title, $link, $subtitle);
- break;
- case 'atom':
- $selfuri = common_root_url() . 'api/direct_messages';
- $selfuri .= ($type == 'received') ? '.atom' : '/sent.atom';
- $taguribase = common_config('integration', 'taguri');
-
- if ($type == 'sent') {
- $id = "tag:$taguribase:SentDirectMessages:" . $user->id;
- } else {
- $id = "tag:$taguribase:DirectMessages:" . $user->id;
- }
-
- $this->show_atom_dmsgs($message, $title, $link, $subtitle,
- $selfuri, $id);
- break;
- case 'json':
- $this->show_json_dmsgs($message);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- }
-
- }
-
- // had to change this from "new" to "create" to avoid PHP reserved word
- function create($args, $apidata)
- {
- parent::handle($args);
-
- if ($_SERVER['REQUEST_METHOD'] != 'POST') {
- $this->clientError(_('This method requires a POST.'),
- 400, $apidata['content-type']);
- return;
- }
-
- $user = $apidata['user'];
- $source = $this->trimmed('source'); // Not supported by Twitter.
-
- $reserved_sources = array('web', 'omb', 'mail', 'xmpp', 'api');
- if (empty($source) || in_array($source, $reserved_sources)) {
- $source = 'api';
- }
-
- $content = $this->trimmed('text');
-
- if (empty($content)) {
- $this->clientError(_('No message text!'),
- $code = 406, $apidata['content-type']);
- } else {
- $content_shortened = common_shorten_links($content);
- if (Message::contentTooLong($content_shortened)) {
- $this->clientError(sprintf(_('That\'s too long. Max message size is %d chars.'),
- Message::maxContent()),
- $code = 406, $apidata['content-type']);
- return;
- }
- }
-
- $other = $this->get_user($this->trimmed('user'));
-
- if (empty($other)) {
- $this->clientError(_('Recipient user not found.'),
- $code = 403, $apidata['content-type']);
- return;
- } else if (!$user->mutuallySubscribed($other)) {
- $this->clientError(_('Can\'t send direct messages to users who aren\'t your friend.'),
- $code = 403, $apidata['content-type']);
- return;
- } else if ($user->id == $other->id) {
- // Sending msgs to yourself is allowed by Twitter
- $this->clientError(_('Don\'t send a message to yourself; just say it to yourself quietly instead.'),
- $code = 403, $apidata['content-type']);
- return;
- }
-
- $message = Message::saveNew($user->id, $other->id,
- html_entity_decode($content, ENT_NOQUOTES, 'UTF-8'), $source);
-
- if (is_string($message)) {
- $this->serverError($message);
- return;
- }
-
- $this->notify($user, $other, $message);
-
- if ($apidata['content-type'] == 'xml') {
- $this->show_single_xml_dmsg($message);
- } elseif ($apidata['content-type'] == 'json') {
- $this->show_single_json_dmsg($message);
- }
-
- }
-
- function destroy($args, $apidata)
- {
- parent::handle($args);
- $this->serverError(_('API method under construction.'), $code=501);
- }
-
- function show_xml_dmsgs($message)
- {
-
- $this->init_document('xml');
- $this->elementStart('direct-messages', array('type' => 'array'));
-
- if (is_array($message)) {
- foreach ($message as $m) {
- $twitter_dm = $this->twitter_dmsg_array($m);
- $this->show_twitter_xml_dmsg($twitter_dm);
- }
- } else {
- while ($message->fetch()) {
- $twitter_dm = $this->twitter_dmsg_array($message);
- $this->show_twitter_xml_dmsg($twitter_dm);
- }
- }
-
- $this->elementEnd('direct-messages');
- $this->end_document('xml');
-
- }
-
- function show_json_dmsgs($message)
- {
-
- $this->init_document('json');
-
- $dmsgs = array();
-
- if (is_array($message)) {
- foreach ($message as $m) {
- $twitter_dm = $this->twitter_dmsg_array($m);
- array_push($dmsgs, $twitter_dm);
- }
- } else {
- while ($message->fetch()) {
- $twitter_dm = $this->twitter_dmsg_array($message);
- array_push($dmsgs, $twitter_dm);
- }
- }
-
- $this->show_json_objects($dmsgs);
- $this->end_document('json');
-
- }
-
- function show_rss_dmsgs($message, $title, $link, $subtitle)
- {
-
- $this->init_document('rss');
-
- $this->elementStart('channel');
- $this->element('title', null, $title);
-
- $this->element('link', null, $link);
- $this->element('description', null, $subtitle);
- $this->element('language', null, 'en-us');
- $this->element('ttl', null, '40');
-
- if (is_array($message)) {
- foreach ($message as $m) {
- $entry = $this->twitter_rss_dmsg_array($m);
- $this->show_twitter_rss_item($entry);
- }
- } else {
- while ($message->fetch()) {
- $entry = $this->twitter_rss_dmsg_array($message);
- $this->show_twitter_rss_item($entry);
- }
- }
-
- $this->elementEnd('channel');
- $this->end_twitter_rss();
-
- }
-
- function show_atom_dmsgs($message, $title, $link, $subtitle, $selfuri, $id)
- {
-
- $this->init_document('atom');
-
- $this->element('title', null, $title);
- $this->element('id', null, $id);
- $this->element('link', array('href' => $link, 'rel' => 'alternate', 'type' => 'text/html'), null);
- $this->element('link', array('href' => $selfuri, 'rel' => 'self',
- 'type' => 'application/atom+xml'), null);
- $this->element('updated', null, common_date_iso8601('now'));
- $this->element('subtitle', null, $subtitle);
-
- if (is_array($message)) {
- foreach ($message as $m) {
- $entry = $this->twitter_rss_dmsg_array($m);
- $this->show_twitter_atom_entry($entry);
- }
- } else {
- while ($message->fetch()) {
- $entry = $this->twitter_rss_dmsg_array($message);
- $this->show_twitter_atom_entry($entry);
- }
- }
-
- $this->end_document('atom');
- }
-
- // swiped from MessageAction. Should it be place in util.php?
- function notify($from, $to, $message)
- {
- mail_notify_message($message, $from, $to);
- # XXX: Jabber, SMS notifications... probably queued
- }
-
-}
diff --git a/actions/twitapifavorites.php b/actions/twitapifavorites.php
deleted file mode 100644
index f8943fe2d..000000000
--- a/actions/twitapifavorites.php
+++ /dev/null
@@ -1,216 +0,0 @@
-<?php
-/*
- * StatusNet - the 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/>.
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once(INSTALLDIR.'/lib/twitterapi.php');
-
-class TwitapifavoritesAction extends TwitterapiAction
-{
-
- function favorites($args, $apidata)
- {
- parent::handle($args);
-
- $this->auth_user = $apidata['user'];
- $user = $this->get_user($apidata['api_arg'], $apidata);
-
- if (empty($user)) {
- if ($apidata['content-type'] == 'xml') {
- $this->show_single_xml_status($notice);
- } elseif ($apidata['content-type'] == 'json') {
- $this->show_single_json_status($notice);
- }
- $this->clientError('Not Found', 404, $apidata['content-type']);
- return;
- }
-
- $profile = $user->getProfile();
-
- $sitename = common_config('site', 'name');
- $title = sprintf(_('%s / Favorites from %s'), $sitename,
- $user->nickname);
- $taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:Favorites:".$user->id;
- $link = common_local_url('favorites',
- array('nickname' => $user->nickname));
- $subtitle = sprintf(_('%s updates favorited by %s / %s.'), $sitename,
- $profile->getBestName(), $user->nickname);
-
- $page = (int)$this->arg('page', 1);
- $count = (int)$this->arg('count', 20);
- $max_id = (int)$this->arg('max_id', 0);
- $since_id = (int)$this->arg('since_id', 0);
- $since = $this->arg('since');
-
- if (!empty($this->auth_user) && $this->auth_user->id == $user->id) {
- $notice = $user->favoriteNotices(($page-1)*$count, $count, true);
- } else {
- $notice = $user->favoriteNotices(($page-1)*$count, $count, false);
- }
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_xml_timeline($notice);
- break;
- case 'rss':
- $this->show_rss_timeline($notice, $title, $link, $subtitle);
- break;
- case 'atom':
- if (isset($apidata['api_arg'])) {
- $selfuri = $selfuri = common_root_url() .
- 'api/favorites/' . $apidata['api_arg'] . '.atom';
- } else {
- $selfuri = $selfuri = common_root_url() .
- 'api/favorites.atom';
- }
- $this->show_atom_timeline($notice, $title, $id, $link,
- $subtitle, null, $selfuri);
- break;
- case 'json':
- $this->show_json_timeline($notice);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- }
-
- }
-
- function create($args, $apidata)
- {
- parent::handle($args);
-
- // Check for RESTfulness
- if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
- $this->clientError(_('This method requires a POST or DELETE.'),
- 400, $apidata['content-type']);
- return;
- }
-
- if (!in_array($apidata['content-type'], array('xml', 'json'))) {
- $this->clientError(_('API method not found!'), $code = 404);
- return;
- }
-
- $user = $apidata['user']; // Always the auth user
- $notice_id = $apidata['api_arg'];
- $notice = Notice::staticGet($notice_id);
-
- if (empty($notice)) {
- $this->clientError(_('No status found with that ID.'),
- 404, $apidata['content-type']);
- return;
- }
-
- // XXX: Twitter lets you fave things repeatedly via api.
- if ($user->hasFave($notice)) {
- $this->clientError(_('This status is already a favorite!'),
- 403, $apidata['content-type']);
- return;
- }
-
- $fave = Fave::addNew($user, $notice);
-
- if (empty($fave)) {
- $this->clientError(_('Could not create favorite.'));
- return;
- }
-
- $this->notify($fave, $notice, $user);
- $user->blowFavesCache();
-
- if ($apidata['content-type'] == 'xml') {
- $this->show_single_xml_status($notice);
- } elseif ($apidata['content-type'] == 'json') {
- $this->show_single_json_status($notice);
- }
-
- }
-
- function destroy($args, $apidata)
- {
- parent::handle($args);
-
- // Check for RESTfulness
- if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
- $this->clientError(_('This method requires a POST or DELETE.'),
- 400, $apidata['content-type']);
- return;
- }
-
- if (!in_array($apidata['content-type'], array('xml', 'json'))) {
- $this->clientError(_('API method not found!'), $code = 404);
- return;
- }
-
- $user = $apidata['user']; // Always the auth user
- $notice_id = $apidata['api_arg'];
- $notice = Notice::staticGet($notice_id);
-
- if (empty($notice)) {
- $this->clientError(_('No status found with that ID.'),
- 404, $apidata['content-type']);
- return;
- }
-
- $fave = new Fave();
- $fave->user_id = $this->id;
- $fave->notice_id = $notice->id;
-
- if (!$fave->find(true)) {
- $this->clientError(_('That status is not a favorite!'),
- 403, $apidata['content-type']);
- return;
- }
-
- $result = $fave->delete();
-
- if (!$result) {
- common_log_db_error($fave, 'DELETE', __FILE__);
- $this->clientError(_('Could not delete favorite.'), 404);
- return;
- }
-
- $user->blowFavesCache();
-
- if ($apidata['content-type'] == 'xml') {
- $this->show_single_xml_status($notice);
- } elseif ($apidata['content-type'] == 'json') {
- $this->show_single_json_status($notice);
- }
-
- }
-
- // XXX: these two funcs swiped from faves.
- // Maybe put in util.php, or some common base class?
-
- function notify($fave, $notice, $user)
- {
- $other = User::staticGet('id', $notice->profile_id);
- if ($other && $other->id != $user->id) {
- if ($other->email && $other->emailnotifyfav) {
- mail_notify_fave($other, $user, $notice);
- }
- # XXX: notify by IM
- # XXX: notify by SMS
- }
- }
-}
diff --git a/actions/twitapifriendships.php b/actions/twitapifriendships.php
deleted file mode 100644
index eea8945c3..000000000
--- a/actions/twitapifriendships.php
+++ /dev/null
@@ -1,250 +0,0 @@
-<?php
-/*
- * StatusNet - the 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/>.
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once(INSTALLDIR.'/lib/twitterapi.php');
-
-class TwitapifriendshipsAction extends TwitterapiAction
-{
-
- function create($args, $apidata)
- {
- parent::handle($args);
-
- if ($_SERVER['REQUEST_METHOD'] != 'POST') {
- $this->clientError(_('This method requires a POST.'),
- 400, $apidata['content-type']);
- return;
- }
-
- $id = $apidata['api_arg'];
- $other = $this->get_user($id);
-
- if (empty($other)) {
- $this->clientError(_('Could not follow user: User not found.'),
- 403, $apidata['content-type']);
- return;
- }
-
- $user = $apidata['user'];
-
- if ($user->isSubscribed($other)) {
- $errmsg = sprintf(_('Could not follow user: %s is already on your list.'),
- $other->nickname);
- $this->clientError($errmsg, 403, $apidata['content-type']);
- return;
- }
-
- $sub = new Subscription();
-
- $sub->query('BEGIN');
-
- $sub->subscriber = $user->id;
- $sub->subscribed = $other->id;
- $sub->created = DB_DataObject_Cast::dateTime(); # current time
-
- $result = $sub->insert();
-
- if (empty($result)) {
- $errmsg = sprintf(_('Could not follow user: %s is already on your list.'),
- $other->nickname);
- $this->clientError($errmsg, 400, $apidata['content-type']);
- return;
- }
-
- $sub->query('COMMIT');
-
- mail_subscribe_notify($other, $user);
-
- $type = $apidata['content-type'];
- $this->init_document($type);
- $this->show_profile($other, $type);
- $this->end_document($type);
-
- }
-
- function destroy($args, $apidata)
- {
- parent::handle($args);
-
- if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
- $this->clientError(_('This method requires a POST or DELETE.'),
- 400, $apidata['content-type']);
- return;
- }
-
- $id = $apidata['api_arg'];
-
- # We can't subscribe to a remote person, but we can unsub
-
- $other = $this->get_profile($id);
- $user = $apidata['user']; // Alwyas the auth user
-
- if ($user->id == $other->id) {
- $this->clientError(_("You cannot unfollow yourself!"),
- 403, $apidata['content-type']);
- return;
- }
-
- $sub = new Subscription();
- $sub->subscriber = $user->id;
- $sub->subscribed = $other->id;
-
- if ($sub->find(true)) {
- $sub->query('BEGIN');
- $sub->delete();
- $sub->query('COMMIT');
- } else {
- $this->clientError(_('You are not friends with the specified user.'),
- 403, $apidata['content-type']);
- return;
- }
-
- $type = $apidata['content-type'];
- $this->init_document($type);
- $this->show_profile($other, $type);
- $this->end_document($type);
-
- }
-
- function exists($args, $apidata)
- {
- parent::handle($args);
-
- if (!in_array($apidata['content-type'], array('xml', 'json'))) {
- $this->clientError(_('API method not found!'), $code = 404);
- return;
- }
-
- $user_a_id = $this->trimmed('user_a');
- $user_b_id = $this->trimmed('user_b');
-
- $user_a = $this->get_user($user_a_id);
- $user_b = $this->get_user($user_b_id);
-
- if (empty($user_a) || empty($user_b)) {
- $this->clientError(_('Two user ids or screen_names must be supplied.'),
- 400, $apidata['content-type']);
- return;
- }
-
- $result = $user_a->isSubscribed($user_b);
-
- switch ($apidata['content-type']) {
- case 'xml':
- $this->init_document('xml');
- $this->element('friends', null, $result);
- $this->end_document('xml');
- break;
- case 'json':
- $this->init_document('json');
- print json_encode($result);
- $this->end_document('json');
- break;
- default:
- break;
- }
-
- }
-
- function show($args, $apidata)
- {
- parent::handle($args);
-
- if (!in_array($apidata['content-type'], array('xml', 'json'))) {
- $this->clientError(_('API method not found!'), $code = 404);
- return;
- }
-
- $source_id = (int)$this->trimmed('source_id');
- $source_screen_name = $this->trimmed('source_screen_name');
-
- // If the source is not specified for an unauthenticated request,
- // the method will return an HTTP 403.
-
- if (empty($source_id) && empty($source_screen_name)) {
- if (empty($apidata['user'])) {
- $this->clientError(_('Could not determine source user.'),
- $code = 403);
- return;
- }
- }
-
- $source = null;
-
- if (!empty($source_id)) {
- $source = User::staticGet($source_id);
- } elseif (!empty($source_screen_name)) {
- $source = User::staticGet('nickname', $source_screen_name);
- } else {
- $source = $apidata['user'];
- }
-
- // If a source or target is specified but does not exist,
- // the method will return an HTTP 404.
-
- if (empty($source)) {
- $this->clientError(_('Could not determine source user.'),
- $code = 404);
- return;
- }
-
- $target_id = (int)$this->trimmed('target_id');
- $target_screen_name = $this->trimmed('target_screen_name');
-
- $target = null;
-
- if (!empty($target_id)) {
- $target = User::staticGet($target_id);
- } elseif (!empty($target_screen_name)) {
- $target = User::staticGet('nickname', $target_screen_name);
- } else {
- $this->clientError(_('Target user not specified.'),
- $code = 403);
- return;
- }
-
- if (empty($target)) {
- $this->clientError(_('Could not find target user.'),
- $code = 404);
- return;
- }
-
- $result = $this->twitter_relationship_array($source, $target);
-
- switch ($apidata['content-type']) {
- case 'xml':
- $this->init_document('xml');
- $this->show_twitter_xml_relationship($result[relationship]);
- $this->end_document('xml');
- break;
- case 'json':
- $this->init_document('json');
- print json_encode($result);
- $this->end_document('json');
- break;
- default:
- break;
- }
- }
-
-}
diff --git a/actions/twitapigroups.php b/actions/twitapigroups.php
deleted file mode 100644
index 4deb1b764..000000000
--- a/actions/twitapigroups.php
+++ /dev/null
@@ -1,329 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * StatusNet extensions to the Twitter-like API for groups
- *
- * 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 Twitter
- * @package StatusNet
- * @author Craig Andrews <candrews@integralblue.com>
- * @author Zach Copley <zach@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/twitterapi.php';
-
-/**
- * Group-specific API methods
- *
- * This class handles StatusNet group API methods.
- *
- * @category Twitter
- * @package StatusNet
- * @author Craig Andrews <candrews@integralblue.com>
- * @author Zach Copley <zach@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
- class TwitapigroupsAction extends TwitterapiAction
- {
-
- function list_groups($args, $apidata)
- {
- parent::handle($args);
-
- common_debug("in groups api action");
-
- $this->auth_user = $apidata['user'];
- $user = $this->get_user($apidata['api_arg'], $apidata);
-
- if (empty($user)) {
- $this->clientError('Not Found', 404, $apidata['content-type']);
- return;
- }
-
- $page = (int)$this->arg('page', 1);
- $count = (int)$this->arg('count', 20);
- $max_id = (int)$this->arg('max_id', 0);
- $since_id = (int)$this->arg('since_id', 0);
- $since = $this->arg('since');
- $group = $user->getGroups(($page-1)*$count,
- $count, $since_id, $max_id, $since);
-
- $sitename = common_config('site', 'name');
- $title = sprintf(_("%s's groups"), $user->nickname);
- $taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:Groups";
- $link = common_root_url();
- $subtitle = sprintf(_("groups %s is a member of on %s"), $user->nickname, $sitename);
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_xml_groups($group);
- break;
- case 'rss':
- $this->show_rss_groups($group, $title, $link, $subtitle);
- break;
- case 'atom':
- $selfuri = common_root_url() . 'api/statusnet/groups/list/' . $user->id . '.atom';
- $this->show_atom_groups($group, $title, $id, $link,
- $subtitle, $selfuri);
- break;
- case 'json':
- $this->show_json_groups($group);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- break;
- }
- }
-
- function list_all($args, $apidata)
- {
- parent::handle($args);
-
- common_debug("in groups api action");
-
- $page = (int)$this->arg('page', 1);
- $count = (int)$this->arg('count', 20);
- $max_id = (int)$this->arg('max_id', 0);
- $since_id = (int)$this->arg('since_id', 0);
- $since = $this->arg('since');
-
- /* TODO:
- Use the $page, $count, $max_id, $since_id, and $since parameters
- */
- $group = new User_group();
- $group->orderBy('created DESC');
- $group->find();
-
- $sitename = common_config('site', 'name');
- $title = sprintf(_("%s groups"), $sitename);
- $taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:Groups";
- $link = common_root_url();
- $subtitle = sprintf(_("groups on %s"), $sitename);
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_xml_groups($group);
- break;
- case 'rss':
- $this->show_rss_groups($group, $title, $link, $subtitle);
- break;
- case 'atom':
- $selfuri = common_root_url() . 'api/statusnet/groups/list_all.atom';
- $this->show_atom_groups($group, $title, $id, $link,
- $subtitle, $selfuri);
- break;
- case 'json':
- $this->show_json_groups($group);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- break;
- }
- }
-
- function show($args, $apidata)
- {
- parent::handle($args);
-
- common_debug("in groups api action");
-
- $this->auth_user = $apidata['user'];
- $group = $this->get_group($apidata['api_arg'], $apidata);
-
- if (empty($group)) {
- $this->clientError('Not Found', 404, $apidata['content-type']);
- return;
- }
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_single_xml_group($group);
- break;
- case 'json':
- $this->show_single_json_group($group);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- }
- }
-
- function timeline($args, $apidata)
- {
- parent::handle($args);
-
- common_debug("in groups api action");
-
- $this->auth_user = $apidata['user'];
- $group = $this->get_group($apidata['api_arg'], $apidata);
-
- if (empty($group)) {
- $this->clientError('Not Found', 404, $apidata['content-type']);
- return;
- }
-
- $sitename = common_config('site', 'name');
- $title = sprintf(_("%s timeline"), $group->nickname);
- $taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:GroupTimeline:".$group->id;
- $link = common_local_url('showgroup',
- array('nickname' => $group->nickname));
- $subtitle = sprintf(_('Updates from %1$s on %2$s!'),
- $group->nickname, $sitename);
-
- $page = (int)$this->arg('page', 1);
- $count = (int)$this->arg('count', 20);
- $max_id = (int)$this->arg('max_id', 0);
- $since_id = (int)$this->arg('since_id', 0);
- $since = $this->arg('since');
-
- $notice = $group->getNotices(($page-1)*$count,
- $count, $since_id, $max_id, $since);
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_xml_timeline($notice);
- break;
- case 'rss':
- $this->show_rss_timeline($notice, $title, $link, $subtitle);
- break;
- case 'atom':
- if (isset($apidata['api_arg'])) {
- $selfuri = common_root_url() .
- 'api/statusnet/groups/timeline/' .
- $apidata['api_arg'] . '.atom';
- } else {
- $selfuri = common_root_url() .
- 'api/statusnet/groups/timeline.atom';
- }
- $this->show_atom_timeline($notice, $title, $id, $link,
- $subtitle, null, $selfuri);
- break;
- case 'json':
- $this->show_json_timeline($notice);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- }
- }
-
- function membership($args, $apidata)
- {
- parent::handle($args);
-
- common_debug("in groups api action");
-
- $this->auth_user = $apidata['user'];
- $group = $this->get_group($apidata['api_arg'], $apidata);
-
- if (empty($group)) {
- $this->clientError('Not Found', 404, $apidata['content-type']);
- return;
- }
-
- $sitename = common_config('site', 'name');
- $title = sprintf(_("Members of %s group"), $group->nickname);
- $taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:GroupMembership:".$group->id;
- $link = common_local_url('showgroup',
- array('nickname' => $group->nickname));
- $subtitle = sprintf(_('Members of %1$s on %2$s'),
- $group->nickname, $sitename);
-
- $page = (int)$this->arg('page', 1);
- $count = (int)$this->arg('count', 20);
- $max_id = (int)$this->arg('max_id', 0);
- $since_id = (int)$this->arg('since_id', 0);
- $since = $this->arg('since');
-
- $member = $group->getMembers(($page-1)*$count,
- $count, $since_id, $max_id, $since);
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_twitter_xml_users($member);
- break;
- //TODO implement the RSS and ATOM content types
- /*case 'rss':
- $this->show_rss_users($member, $title, $link, $subtitle);
- break;*/
- /*case 'atom':
- if (isset($apidata['api_arg'])) {
- $selfuri = common_root_url() .
- 'api/statusnet/groups/membership/' .
- $apidata['api_arg'] . '.atom';
- } else {
- $selfuri = common_root_url() .
- 'api/statusnet/groups/membership.atom';
- }
- $this->show_atom_users($member, $title, $id, $link,
- $subtitle, null, $selfuri);
- break;*/
- case 'json':
- $this->show_json_users($member);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- }
- }
-
- function is_member($args, $apidata)
- {
- parent::handle($args);
-
- common_debug("in groups api action");
-
- $this->auth_user = $apidata['user'];
- $group = User_group::staticGet($args['group_id']);
- if(! $group){
- $this->clientError(_('Group not found'), $code = 500);
- }
- $user = User::staticGet('id', $args['user_id']);
- if(! $user){
- $this->clientError(_('User not found'), $code = 500);
- }
-
- $is_member=$user->isMember($group);
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->init_document('xml');
- $this->element('is_member', null, $is_member);
- $this->end_document('xml');
- break;
- case 'json':
- $this->init_document('json');
- $this->show_json_objects(array('is_member'=>$is_member));
- $this->end_document('json');
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- }
- }
-}
diff --git a/actions/twitapihelp.php b/actions/twitapihelp.php
deleted file mode 100644
index 81381620e..000000000
--- a/actions/twitapihelp.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-/*
- * StatusNet - the 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/>.
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once(INSTALLDIR.'/lib/twitterapi.php');
-
-class TwitapihelpAction extends TwitterapiAction
-{
-
- /* Returns the string "ok" in the requested format with a 200 OK HTTP status code.
- * URL:http://identi.ca/api/help/test.format
- * Formats: xml, json
- */
- function test($args, $apidata)
- {
- parent::handle($args);
-
- if ($apidata['content-type'] == 'xml') {
- $this->init_document('xml');
- $this->element('ok', null, 'true');
- $this->end_document('xml');
- } elseif ($apidata['content-type'] == 'json') {
- $this->init_document('json');
- print '"ok"';
- $this->end_document('json');
- } else {
- $this->clientError(_('API method not found!'), $code=404);
- }
-
- }
-
- function downtime_schedule($args, $apidata)
- {
- parent::handle($args);
- $this->serverError(_('API method under construction.'), $code=501);
- }
-
-} \ No newline at end of file
diff --git a/actions/twitapinotifications.php b/actions/twitapinotifications.php
deleted file mode 100644
index 0653e69ab..000000000
--- a/actions/twitapinotifications.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-/*
- * StatusNet - the 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/>.
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
-
-require_once(INSTALLDIR.'/lib/twitterapi.php');
-
-# This naming convention looks real sick
-class TwitapinotificationsAction extends TwitterapiAction
-{
-
- function follow($args, $apidata)
- {
- parent::handle($args);
- $this->serverError(_('API method under construction.'), $code=501);
- }
-
- function leave($args, $apidata)
- {
- parent::handle($args);
- $this->serverError(_('API method under construction.'), $code=501);
- }
-
-} \ No newline at end of file
diff --git a/actions/twitapisearchatom.php b/actions/twitapisearchatom.php
index 2f587d604..7d618c471 100644
--- a/actions/twitapisearchatom.php
+++ b/actions/twitapisearchatom.php
@@ -31,7 +31,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
-require_once INSTALLDIR.'/lib/twitterapi.php';
+require_once INSTALLDIR.'/lib/api.php';
/**
* Action for outputting search results in Twitter compatible Atom
@@ -46,10 +46,10 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*
- * @see TwitterapiAction
+ * @see ApiAction
*/
-class TwitapisearchatomAction extends TwitterapiAction
+class TwitapisearchatomAction extends ApiAction
{
var $cnt;
@@ -340,7 +340,7 @@ class TwitapisearchatomAction extends TwitterapiAction
// TODO: Here is where we'd put in a link to an atom feed for threads
$this->element("twitter:source", null,
- htmlentities($this->source_link($notice->source)));
+ htmlentities($this->sourceLink($notice->source)));
$this->elementStart('author');
diff --git a/actions/twitapisearchjson.php b/actions/twitapisearchjson.php
index c628ee624..c7fa741a0 100644
--- a/actions/twitapisearchjson.php
+++ b/actions/twitapisearchjson.php
@@ -31,7 +31,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
-require_once INSTALLDIR.'/lib/twitterapi.php';
+require_once INSTALLDIR.'/lib/api.php';
require_once INSTALLDIR.'/lib/jsonsearchresultslist.php';
/**
@@ -42,10 +42,10 @@ require_once INSTALLDIR.'/lib/jsonsearchresultslist.php';
* @author Zach Copley <zach@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
- * @see TwitterapiAction
+ * @see ApiAction
*/
-class TwitapisearchjsonAction extends TwitterapiAction
+class TwitapisearchjsonAction extends ApiAction
{
var $query;
var $lang;
@@ -134,9 +134,9 @@ class TwitapisearchjsonAction extends TwitterapiAction
$results = new JSONSearchResultsList($notice, $q, $this->rpp, $this->page);
- $this->init_document('json');
+ $this->initDocument('json');
$results->show();
- $this->end_document('json');
+ $this->endDocument('json');
}
/**
diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php
deleted file mode 100644
index ad6654dff..000000000
--- a/actions/twitapistatuses.php
+++ /dev/null
@@ -1,606 +0,0 @@
-<?php
-/*
- * StatusNet - the 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/>.
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once(INSTALLDIR.'/lib/twitterapi.php');
-
-class TwitapistatusesAction extends TwitterapiAction
-{
-
- function public_timeline($args, $apidata)
- {
- // XXX: To really live up to the spec we need to build a list
- // of notices by users who have custom avatars, so fix this SQL -- Zach
-
- parent::handle($args);
-
- $sitename = common_config('site', 'name');
- $title = sprintf(_("%s public timeline"), $sitename);
- $taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:PublicTimeline";
- $link = common_root_url();
- $subtitle = sprintf(_("%s updates from everyone!"), $sitename);
-
- $page = (int)$this->arg('page', 1);
- $count = (int)$this->arg('count', 20);
- $max_id = (int)$this->arg('max_id', 0);
- $since_id = (int)$this->arg('since_id', 0);
- $since = $this->arg('since');
-
- $notice = Notice::publicStream(($page-1)*$count, $count, $since_id,
- $max_id, $since);
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_xml_timeline($notice);
- break;
- case 'rss':
- $this->show_rss_timeline($notice, $title, $link, $subtitle);
- break;
- case 'atom':
- $selfuri = common_root_url() . 'api/statuses/public_timeline.atom';
- $this->show_atom_timeline($notice, $title, $id, $link,
- $subtitle, null, $selfuri);
- break;
- case 'json':
- $this->show_json_timeline($notice);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- break;
- }
-
- }
-
- function friends_timeline($args, $apidata)
- {
- parent::handle($args);
-
- $this->auth_user = $apidata['user'];
- $user = $this->get_user($apidata['api_arg'], $apidata);
-
- if (empty($user)) {
- $this->clientError(_('No such user!'), 404,
- $apidata['content-type']);
- return;
- }
-
- $profile = $user->getProfile();
- $sitename = common_config('site', 'name');
- $title = sprintf(_("%s and friends"), $user->nickname);
- $taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:FriendsTimeline:" . $user->id;
- $link = common_local_url('all',
- array('nickname' => $user->nickname));
- $subtitle = sprintf(_('Updates from %1$s and friends on %2$s!'),
- $user->nickname, $sitename);
-
- $page = (int)$this->arg('page', 1);
- $count = (int)$this->arg('count', 20);
- $max_id = (int)$this->arg('max_id', 0);
- $since_id = (int)$this->arg('since_id', 0);
- $since = $this->arg('since');
-
- if (!empty($this->auth_user) && $this->auth_user->id == $user->id) {
- $notice = $user->noticeInbox(($page-1)*$count,
- $count, $since_id, $max_id, $since);
- } else {
- $notice = $user->noticesWithFriends(($page-1)*$count,
- $count, $since_id, $max_id, $since);
- }
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_xml_timeline($notice);
- break;
- case 'rss':
- $this->show_rss_timeline($notice, $title, $link, $subtitle);
- break;
- case 'atom':
- if (isset($apidata['api_arg'])) {
- $selfuri = common_root_url() .
- 'api/statuses/friends_timeline/' .
- $apidata['api_arg'] . '.atom';
- } else {
- $selfuri = common_root_url() .
- 'api/statuses/friends_timeline.atom';
- }
- $this->show_atom_timeline($notice, $title, $id, $link,
- $subtitle, null, $selfuri);
- break;
- case 'json':
- $this->show_json_timeline($notice);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- }
-
- }
-
- function user_timeline($args, $apidata)
- {
- parent::handle($args);
-
- $this->auth_user = $apidata['user'];
- $user = $this->get_user($apidata['api_arg'], $apidata);
-
- if (empty($user)) {
- $this->clientError('Not Found', 404, $apidata['content-type']);
- return;
- }
-
- $profile = $user->getProfile();
-
- $sitename = common_config('site', 'name');
- $title = sprintf(_("%s timeline"), $user->nickname);
- $taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:UserTimeline:".$user->id;
- $link = common_local_url('showstream',
- array('nickname' => $user->nickname));
- $subtitle = sprintf(_('Updates from %1$s on %2$s!'),
- $user->nickname, $sitename);
-
- # FriendFeed's SUP protocol
- # Also added RSS and Atom feeds
-
- $suplink = common_local_url('sup', null, null, $user->id);
- header('X-SUP-ID: '.$suplink);
-
- $page = (int)$this->arg('page', 1);
- $count = (int)$this->arg('count', 20);
- $max_id = (int)$this->arg('max_id', 0);
- $since_id = (int)$this->arg('since_id', 0);
- $since = $this->arg('since');
-
- $notice = $user->getNotices(($page-1)*$count,
- $count, $since_id, $max_id, $since);
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_xml_timeline($notice);
- break;
- case 'rss':
- $this->show_rss_timeline($notice, $title, $link,
- $subtitle, $suplink);
- break;
- case 'atom':
- if (isset($apidata['api_arg'])) {
- $selfuri = common_root_url() .
- 'api/statuses/user_timeline/' .
- $apidata['api_arg'] . '.atom';
- } else {
- $selfuri = common_root_url() .
- 'api/statuses/user_timeline.atom';
- }
- $this->show_atom_timeline($notice, $title, $id, $link,
- $subtitle, $suplink, $selfuri);
- break;
- case 'json':
- $this->show_json_timeline($notice);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- }
-
- }
-
- function update($args, $apidata)
- {
- parent::handle($args);
-
- if (!in_array($apidata['content-type'], array('xml', 'json'))) {
- $this->clientError(_('API method not found!'), $code = 404);
- return;
- }
-
- if ($_SERVER['REQUEST_METHOD'] != 'POST') {
- $this->clientError(_('This method requires a POST.'),
- 400, $apidata['content-type']);
- return;
- }
-
- $user = $apidata['user']; // Always the auth user
-
- $status = $this->trimmed('status');
- $source = $this->trimmed('source');
- $in_reply_to_status_id =
- intval($this->trimmed('in_reply_to_status_id'));
- $reserved_sources = array('web', 'omb', 'mail', 'xmpp', 'api');
-
- if (empty($source) || in_array($source, $reserved_sources)) {
- $source = 'api';
- }
-
- if (empty($status)) {
-
- // XXX: Note: In this case, Twitter simply returns '200 OK'
- // No error is given, but the status is not posted to the
- // user's timeline. Seems bad. Shouldn't we throw an
- // errror? -- Zach
- return;
-
- } else {
-
- $status_shortened = common_shorten_links($status);
-
- if (Notice::contentTooLong($status_shortened)) {
-
- // XXX: Twitter truncates anything over 140, flags the status
- // as "truncated." Sending this error may screw up some clients
- // that assume Twitter will truncate for them. Should we just
- // truncate too? -- Zach
- $this->clientError(sprintf(_('That\'s too long. Max notice size is %d chars.'),
- Notice::maxContent()),
- $code = 406, $apidata['content-type']);
- return;
- }
- }
-
- // Check for commands
- $inter = new CommandInterpreter();
- $cmd = $inter->handle_command($user, $status_shortened);
-
- if ($cmd) {
-
- if ($this->supported($cmd)) {
- $cmd->execute(new Channel());
- }
-
- // cmd not supported? Twitter just returns your latest status.
- // And, it returns your last status whether the cmd was successful
- // or not!
- $n = $user->getCurrentNotice();
- $apidata['api_arg'] = $n->id;
- } else {
-
- $reply_to = null;
-
- if ($in_reply_to_status_id) {
-
- // check whether notice actually exists
- $reply = Notice::staticGet($in_reply_to_status_id);
-
- if ($reply) {
- $reply_to = $in_reply_to_status_id;
- } else {
- $this->clientError(_('Not found'), $code = 404,
- $apidata['content-type']);
- return;
- }
- }
-
- $notice = Notice::saveNew($user->id,
- html_entity_decode($status, ENT_NOQUOTES, 'UTF-8'),
- $source, 1, $reply_to);
-
- if (is_string($notice)) {
- $this->serverError($notice);
- return;
- }
-
- common_broadcast_notice($notice);
- $apidata['api_arg'] = $notice->id;
- }
-
- $this->show($args, $apidata);
- }
-
- function mentions($args, $apidata)
- {
- parent::handle($args);
-
- $user = $this->get_user($apidata['api_arg'], $apidata);
- $this->auth_user = $apidata['user'];
-
- if (empty($user)) {
- $this->clientError(_('No such user!'), 404,
- $apidata['content-type']);
- return;
- }
-
- $profile = $user->getProfile();
-
- $sitename = common_config('site', 'name');
- $title = sprintf(_('%1$s / Updates mentioning %2$s'),
- $sitename, $user->nickname);
- $taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:Mentions:".$user->id;
- $link = common_local_url('replies',
- array('nickname' => $user->nickname));
- $subtitle = sprintf(_('%1$s updates that reply to updates from %2$s / %3$s.'),
- $sitename, $user->nickname, $profile->getBestName());
-
- $page = (int)$this->arg('page', 1);
- $count = (int)$this->arg('count', 20);
- $max_id = (int)$this->arg('max_id', 0);
- $since_id = (int)$this->arg('since_id', 0);
- $since = $this->arg('since');
-
- $notice = $user->getReplies(($page-1)*$count,
- $count, $since_id, $max_id, $since);
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_xml_timeline($notice);
- break;
- case 'rss':
- $this->show_rss_timeline($notice, $title, $link, $subtitle);
- break;
- case 'atom':
- $selfuri = common_root_url() .
- ltrim($_SERVER['QUERY_STRING'], 'p=');
- $this->show_atom_timeline($notice, $title, $id, $link, $subtitle,
- null, $selfuri);
- break;
- case 'json':
- $this->show_json_timeline($notice);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- }
-
- }
-
- function replies($args, $apidata)
- {
- call_user_func(array($this, 'mentions'), $args, $apidata);
- }
-
- function show($args, $apidata)
- {
- parent::handle($args);
-
- if (!in_array($apidata['content-type'], array('xml', 'json'))) {
- $this->clientError(_('API method not found!'), $code = 404);
- return;
- }
-
- // 'id' is an undocumented parameter in Twitter's API. Several
- // clients make use of it, so we support it too.
-
- // show.json?id=12345 takes precedence over /show/12345.json
-
- $this->auth_user = $apidata['user'];
- $notice_id = $this->trimmed('id');
-
- if (empty($notice_id)) {
- $notice_id = $apidata['api_arg'];
- }
-
- $notice = Notice::staticGet((int)$notice_id);
-
- if ($notice) {
- if ($apidata['content-type'] == 'xml') {
- $this->show_single_xml_status($notice);
- } elseif ($apidata['content-type'] == 'json') {
- $this->show_single_json_status($notice);
- }
- } else {
- // XXX: Twitter just sets a 404 header and doens't bother
- // to return an err msg
- $deleted = Deleted_notice::staticGet($notice_id);
- if (!empty($deleted)) {
- $this->clientError(_('Status deleted.'),
- 410, $apidata['content-type']);
- } else {
- $this->clientError(_('No status with that ID found.'),
- 404, $apidata['content-type']);
- }
- }
- }
-
- function destroy($args, $apidata)
- {
- parent::handle($args);
-
- if (!in_array($apidata['content-type'], array('xml', 'json'))) {
- $this->clientError(_('API method not found!'), $code = 404);
- return;
- }
-
- // Check for RESTfulness
- if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
- // XXX: Twitter just prints the err msg, no XML / JSON.
- $this->clientError(_('This method requires a POST or DELETE.'),
- 400, $apidata['content-type']);
- return;
- }
-
- $user = $apidata['user']; // Always the auth user
- $notice_id = $apidata['api_arg'];
- $notice = Notice::staticGet($notice_id);
-
- if (empty($notice)) {
- $this->clientError(_('No status found with that ID.'),
- 404, $apidata['content-type']);
- return;
- }
-
- if ($user->id == $notice->profile_id) {
- $replies = new Reply;
- $replies->get('notice_id', $notice_id);
- $replies->delete();
- $notice->delete();
-
- if ($apidata['content-type'] == 'xml') {
- $this->show_single_xml_status($notice);
- } elseif ($apidata['content-type'] == 'json') {
- $this->show_single_json_status($notice);
- }
- } else {
- $this->clientError(_('You may not delete another user\'s status.'),
- 403, $apidata['content-type']);
- }
-
- }
-
- function friends($args, $apidata)
- {
- parent::handle($args);
- $includeStatuses=! (boolean) $args['lite'];
- return $this->subscriptions($apidata, 'subscribed', 'subscriber', false, $includeStatuses);
- }
-
- function friendsIDs($args, $apidata)
- {
- parent::handle($args);
- return $this->subscriptions($apidata, 'subscribed', 'subscriber', true);
- }
-
- function followers($args, $apidata)
- {
- parent::handle($args);
- $includeStatuses=! (boolean) $args['lite'];
- return $this->subscriptions($apidata, 'subscriber', 'subscribed', false, $includeStatuses);
- }
-
- function followersIDs($args, $apidata)
- {
- parent::handle($args);
- return $this->subscriptions($apidata, 'subscriber', 'subscribed', true);
- }
-
- function subscriptions($apidata, $other_attr, $user_attr, $onlyIDs=false, $includeStatuses=true)
- {
- $this->auth_user = $apidata['user'];
- $user = $this->get_user($apidata['api_arg'], $apidata);
-
- if (empty($user)) {
- $this->clientError('Not Found', 404, $apidata['content-type']);
- return;
- }
-
- $profile = $user->getProfile();
-
- $sub = new Subscription();
- $sub->$user_attr = $profile->id;
-
- $sub->orderBy('created DESC');
-
- // Normally, page 100 friends at a time
-
- if (!$onlyIDs) {
- $page = $this->arg('page', 1);
- $count = $this->arg('count', 100);
- $sub->limit(($page-1)*$count, $count);
- } else {
-
- // If we're just looking at IDs, return
- // ALL of them, unless the user specifies a page,
- // in which case, return 500 per page.
-
- $page = $this->arg('page');
- if (!empty($page)) {
- if ($page < 1) {
- $page = 1;
- }
- $count = 500;
- $sub->limit(($page-1)*$count, $count);
- }
- }
-
- $others = array();
-
- if ($sub->find()) {
- while ($sub->fetch()) {
- $others[] = Profile::staticGet($sub->$other_attr);
- }
- } else {
- // user has no followers
- }
-
- $type = $apidata['content-type'];
-
- $this->init_document($type);
-
- if ($onlyIDs) {
- $this->showIDs($others, $type);
- } else {
- $this->show_profiles($others, $type, $includeStatuses);
- }
-
- $this->end_document($type);
- }
-
- function show_profiles($profiles, $type, $includeStatuses)
- {
- switch ($type) {
- case 'xml':
- $this->elementStart('users', array('type' => 'array'));
- foreach ($profiles as $profile) {
- $this->show_profile($profile,$type,null,$includeStatuses);
- }
- $this->elementEnd('users');
- break;
- case 'json':
- $arrays = array();
- foreach ($profiles as $profile) {
- $arrays[] = $this->twitter_user_array($profile, $includeStatuses);
- }
- print json_encode($arrays);
- break;
- default:
- $this->clientError(_('unsupported file type'));
- }
- }
-
- function showIDs($profiles, $type)
- {
- switch ($type) {
- case 'xml':
- $this->elementStart('ids');
- foreach ($profiles as $profile) {
- $this->element('id', null, $profile->id);
- }
- $this->elementEnd('ids');
- break;
- case 'json':
- $ids = array();
- foreach ($profiles as $profile) {
- $ids[] = (int)$profile->id;
- }
- print json_encode($ids);
- break;
- default:
- $this->clientError(_('unsupported file type'));
- }
- }
-
- function featured($args, $apidata)
- {
- parent::handle($args);
- $this->serverError(_('API method under construction.'), $code=501);
- }
-
- function supported($cmd)
- {
- $cmdlist = array('MessageCommand', 'SubCommand', 'UnsubCommand',
- 'FavCommand', 'OnCommand', 'OffCommand');
-
- if (in_array(get_class($cmd), $cmdlist)) {
- return true;
- }
-
- return false;
- }
-
-}
diff --git a/actions/twitapistatusnet.php b/actions/twitapistatusnet.php
deleted file mode 100644
index 490f11dce..000000000
--- a/actions/twitapistatusnet.php
+++ /dev/null
@@ -1,175 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * StatusNet-only extensions to the Twitter-like API
- *
- * 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 Twitter
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @copyright 2008 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/twitterapi.php';
-
-/**
- * StatusNet-specific API methods
- *
- * This class handles all /statusnet/ API methods.
- *
- * @category Twitter
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @copyright 2008 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-class TwitapistatusnetAction extends TwitterapiAction
-{
- /**
- * A version stamp for the API
- *
- * Returns a version number for this version of StatusNet, which
- * should make things a bit easier for upgrades.
- * URL: http://identi.ca/api/statusnet/version.(xml|json)
- * Formats: xml, json
- *
- * @param array $args Web arguments
- * @param array $apidata Twitter API data
- *
- * @return void
- *
- * @see ApiAction::process_command()
- */
-
- function version($args, $apidata)
- {
- parent::handle($args);
- switch ($apidata['content-type']) {
- case 'xml':
- $this->init_document('xml');
- $this->element('version', null, STATUSNET_VERSION);
- $this->end_document('xml');
- break;
- case 'json':
- $this->init_document('json');
- print '"'.STATUSNET_VERSION.'"';
- $this->end_document('json');
- break;
- default:
- $this->clientError(_('API method not found!'), $code=404);
- }
- }
-
- /**
- * Dump of configuration variables
- *
- * Gives a full dump of configuration variables for this instance
- * of StatusNet, minus variables that may be security-sensitive (like
- * passwords).
- * URL: http://identi.ca/api/statusnet/config.(xml|json)
- * Formats: xml, json
- *
- * @param array $args Web arguments
- * @param array $apidata Twitter API data
- *
- * @return void
- *
- * @see ApiAction::process_command()
- */
-
- function config($args, $apidata)
- {
- static $keys = array('site' => array('name', 'server', 'theme', 'path', 'fancy', 'language',
- 'email', 'broughtby', 'broughtbyurl', 'closed',
- 'inviteonly', 'private'),
- 'license' => array('url', 'title', 'image'),
- 'nickname' => array('featured'),
- 'throttle' => array('enabled', 'count', 'timespan'),
- 'xmpp' => array('enabled', 'server', 'user'));
-
- parent::handle($args);
-
- switch ($apidata['content-type']) {
- case 'xml':
- $this->init_document('xml');
- $this->elementStart('config');
- // XXX: check that all sections and settings are legal XML elements
- foreach ($keys as $section => $settings) {
- $this->elementStart($section);
- foreach ($settings as $setting) {
- $value = common_config($section, $setting);
- if (is_array($value)) {
- $value = implode(',', $value);
- } else if ($value === false) {
- $value = 'false';
- } else if ($value === true) {
- $value = 'true';
- }
- $this->element($setting, null, $value);
- }
- $this->elementEnd($section);
- }
- $this->elementEnd('config');
- $this->end_document('xml');
- break;
- case 'json':
- $result = array();
- foreach ($keys as $section => $settings) {
- $result[$section] = array();
- foreach ($settings as $setting) {
- $result[$section][$setting] = common_config($section, $setting);
- }
- }
- $this->init_document('json');
- $this->show_json_objects($result);
- $this->end_document('json');
- break;
- default:
- $this->clientError(_('API method not found!'), $code=404);
- }
- }
-
- /**
- * WADL description of the API
- *
- * Gives a WADL description of the API provided by this version of the
- * software.
- *
- * @param array $args Web arguments
- * @param array $apidata Twitter API data
- *
- * @return void
- *
- * @see ApiAction::process_command()
- */
-
- function wadl($args, $apidata)
- {
- parent::handle($args);
- $this->serverError(_('API method under construction.'), 501);
- }
-
-}
diff --git a/actions/twitapitags.php b/actions/twitapitags.php
deleted file mode 100644
index 0bcc55d37..000000000
--- a/actions/twitapitags.php
+++ /dev/null
@@ -1,113 +0,0 @@
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * StatusNet extensions to the Twitter-like API for groups
- *
- * 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 Twitter
- * @package StatusNet
- * @author Craig Andrews <candrews@integralblue.com>
- * @author Zach Copley <zach@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/twitterapi.php';
-
-/**
- * Group-specific API methods
- *
- * This class handles StatusNet group API methods.
- *
- * @category Twitter
- * @package StatusNet
- * @author Craig Andrews <candrews@integralblue.com>
- * @author Zach Copley <zach@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
- class TwitapitagsAction extends TwitterapiAction
- {
-
- function timeline($args, $apidata)
- {
- parent::handle($args);
-
- common_debug("in tags api action");
-
- $this->auth_user = $apidata['user'];
- $tag = $apidata['api_arg'];
-
- if (empty($tag)) {
- $this->clientError('Not Found', 404, $apidata['content-type']);
- return;
- }
-
- $sitename = common_config('site', 'name');
- $title = sprintf(_("Notices tagged with %s"), $tag);
- $taguribase = common_config('integration', 'taguri');
- $id = "tag:$taguribase:TagTimeline:".$tag;
- $link = common_local_url('tag',
- array('tag' => $tag));
- $subtitle = sprintf(_('Updates tagged with %1$s on %2$s!'),
- $tag, $sitename);
-
- $page = (int)$this->arg('page', 1);
- $count = (int)$this->arg('count', 20);
- $max_id = (int)$this->arg('max_id', 0);
- $since_id = (int)$this->arg('since_id', 0);
- $since = $this->arg('since');
-
- # XXX: support max_id, since_id, and since arguments
- $notice = Notice_tag::getStream($tag, ($page-1)*$count, $count + 1);
-
- switch($apidata['content-type']) {
- case 'xml':
- $this->show_xml_timeline($notice);
- break;
- case 'rss':
- $this->show_rss_timeline($notice, $title, $link, $subtitle);
- break;
- case 'atom':
- if (isset($apidata['api_arg'])) {
- $selfuri = common_root_url() .
- 'api/statusnet/tags/timeline/' .
- $apidata['api_arg'] . '.atom';
- } else {
- $selfuri = common_root_url() .
- 'api/statusnet/tags/timeline.atom';
- }
- $this->show_atom_timeline($notice, $title, $id, $link,
- $subtitle, null, $selfuri);
- break;
- case 'json':
- $this->show_json_timeline($notice);
- break;
- default:
- $this->clientError(_('API method not found!'), $code = 404);
- }
- }
-
-}
diff --git a/actions/twitapitrends.php b/actions/twitapitrends.php
index 83ab28f35..779405e6d 100644
--- a/actions/twitapitrends.php
+++ b/actions/twitapitrends.php
@@ -31,7 +31,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
-require_once INSTALLDIR.'/lib/twitterapi.php';
+require_once INSTALLDIR.'/lib/api.php';
/**
* Returns the top ten queries that are currently trending
@@ -42,10 +42,10 @@ require_once INSTALLDIR.'/lib/twitterapi.php';
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*
- * @see TwitterapiAction
+ * @see ApiAction
*/
-class TwitapitrendsAction extends TwitterapiAction
+class TwitapitrendsAction extends ApiAction
{
var $callback;
diff --git a/actions/twitapiusers.php b/actions/twitapiusers.php
deleted file mode 100644
index 703fa6754..000000000
--- a/actions/twitapiusers.php
+++ /dev/null
@@ -1,80 +0,0 @@
-<?php
-/*
- * StatusNet - the 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/>.
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once(INSTALLDIR.'/lib/twitterapi.php');
-
-class TwitapiusersAction extends TwitterapiAction
-{
-
- function show($args, $apidata)
- {
- parent::handle($args);
-
- if (!in_array($apidata['content-type'], array('xml', 'json'))) {
- $this->clientError(_('API method not found!'), $code = 404);
- return;
- }
-
- $user = null;
- $email = $this->arg('email');
-
- // XXX: email field deprecated in Twitter's API
-
- if ($email) {
- $user = User::staticGet('email', $email);
- } else {
- $user = $this->get_user($apidata['api_arg'], $apidata);
- }
-
- if (empty($user)) {
- $this->clientError(_('Not found.'), 404, $apidata['content-type']);
- return;
- }
-
- $profile = $user->getProfile();
-
- if (!$profile) {
- common_server_error(_('User has no profile.'));
- return;
- }
-
- $twitter_user = $this->twitter_user_array($user->getProfile(), true);
-
- if ($apidata['content-type'] == 'xml') {
- $this->init_document('xml');
- $this->show_twitter_xml_user($twitter_user);
- $this->end_document('xml');
- } elseif ($apidata['content-type'] == 'json') {
- $this->init_document('json');
- $this->show_json_objects($twitter_user);
- $this->end_document('json');
- } else {
-
- // This is in case 'show' was called via /account/verify_credentials
- // without a format (xml or json).
- header('Content-Type: text/html; charset=utf-8');
- print 'Authorized';
- }
-
- }
-}
diff --git a/actions/updateprofile.php b/actions/updateprofile.php
index d9cc7f7f3..3cec9523c 100644
--- a/actions/updateprofile.php
+++ b/actions/updateprofile.php
@@ -55,46 +55,13 @@ class UpdateprofileAction extends Action
*/
function prepare($argarray)
{
- $version = $req->get_parameter('omb_version');
- if ($version != OMB_VERSION_01) {
- $this->clientError(_('Unsupported OMB version'), 400);
- return false;
- }
- # First, check to see if listenee exists
- $listenee = $req->get_parameter('omb_listenee');
- $remote = Remote_profile::staticGet('uri', $listenee);
- if (!$remote) {
- $this->clientError(_('Profile unknown'), 404);
- return false;
- }
- # Second, check to see if they should be able to post updates!
- # We see if there are any subscriptions to that remote user with
- # the given token.
-
- $sub = new Subscription();
- $sub->subscribed = $remote->id;
- $sub->token = $token->key;
- if (!$sub->find(true)) {
- $this->clientError(_('You did not send us that profile'), 403);
- return false;
- }
-
- $profile = Profile::staticGet('id', $remote->id);
- if (!$profile) {
- # This one is our fault
- $this->serverError(_('Remote profile with no matching profile'), 500);
- return false;
- }
- $nickname = $req->get_parameter('omb_listenee_nickname');
- if ($nickname && !Validate::string($nickname, array('min_length' => 1,
- 'max_length' => 64,
- 'format' => NICKNAME_FMT))) {
- $this->clientError(_('Nickname must have only lowercase letters and numbers and no spaces.'));
- return false;
- }
- $license = $req->get_parameter('omb_listenee_license');
- if ($license && !common_valid_http_url($license)) {
- $this->clientError(sprintf(_("Invalid license URL '%s'"), $license));
+ parent::prepare($argarray);
+ $license = $_POST['omb_listenee_license'];
+ $site_license = common_config('license', 'url');
+ if (!common_compatible_license($license, $site_license)) {
+ $this->clientError(sprintf(_('Listenee stream license ā€˜%sā€™ is not '.
+ 'compatible with site license ā€˜%sā€™.'),
+ $license, $site_license));
return false;
}
return true;
@@ -113,4 +80,4 @@ class UpdateprofileAction extends Action
return;
}
}
-} \ No newline at end of file
+}
diff --git a/actions/userrss.php b/actions/userrss.php
index fa6d588cd..19e610551 100644
--- a/actions/userrss.php
+++ b/actions/userrss.php
@@ -25,7 +25,6 @@ require_once(INSTALLDIR.'/lib/rssaction.php');
class UserrssAction extends Rss10Action
{
- var $user = null;
var $tag = null;
function prepare($args)
@@ -39,6 +38,7 @@ class UserrssAction extends Rss10Action
$this->clientError(_('No such user.'));
return false;
} else {
+ $this->notices = $this->getNotices($this->limit);
return true;
}
}
@@ -64,9 +64,8 @@ class UserrssAction extends Rss10Action
function getNotices($limit=0)
{
-
$user = $this->user;
-
+
if (is_null($user)) {
return null;
}