From 49b701f9ec6d7795147f94c43eaf744a96efb199 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 23 Sep 2009 13:45:51 -0700 Subject: [PATCH 01/49] Started refactoring API into individual actions --- actions/apifriendstimeline.php | 161 +++++++++++++++++++++++++++++++++ lib/router.php | 16 +++- lib/twitterapi.php | 127 +++++++++++++++++++++++++- 3 files changed, 297 insertions(+), 7 deletions(-) create mode 100644 actions/apifriendstimeline.php diff --git a/actions/apifriendstimeline.php b/actions/apifriendstimeline.php new file mode 100644 index 0000000000..ea38ec022e --- /dev/null +++ b/actions/apifriendstimeline.php @@ -0,0 +1,161 @@ +. + * + * @category Personal + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.php'; + +class ApifriendstimelineAction extends TwitterapiAction +{ + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + return true; + + } + + function handle($args) { + + parent::handle($args); + common_debug(var_export($args, true)); + + if ($this->requiresAuth()) { + if ($this->showBasicAuthHeader()) { + $this->showTimeline(); + } + } else { + $this->showTimeline(); + } + } + + function showTimeline() + { + common_debug('Auth user = ' . var_export($this->auth_user, true)); + + $user = $this->getTargetUser($this->arg('id')); + + if (empty($user)) { + $this->clientError(_('No such user!'), 404, $this->arg('format')); + 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($this->arg('format')) { + case 'xml': + $this->show_xml_timeline($notice); + break; + case 'rss': + $this->show_rss_timeline($notice, $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->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 requiresAuth() + { + return true; + } + + /** + * Is this page read-only? + * + * @return boolean true + */ + + function isReadOnly($args) + { + return true; + } + + /** + * When was this page last modified? + * + */ + + function lastModified() + { + + } + +} \ No newline at end of file diff --git a/lib/router.php b/lib/router.php index 2c4d63b0d7..0e5fe3a54f 100644 --- a/lib/router.php +++ b/lib/router.php @@ -262,15 +262,27 @@ class Router // statuses API + $m->connect('api/statuses/friends_timeline.:format', + array('action' => 'apifriendstimeline', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statuses/friends_timeline/:id.:format', + array('action' => 'apifriendstimeline', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statuses/home_timeline', + array('action' => 'apifriendstimeline')); + $m->connect('api/statuses/:method', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(public_timeline|home_timeline|friends_timeline|user_timeline|update|replies|mentions|show|friends|followers|featured)(\.(atom|rss|xml|json))?')); + array('method' => '(public_timeline|user_timeline|update|replies|mentions|show|friends|followers|featured)(\.(atom|rss|xml|json))?')); $m->connect('api/statuses/:method/:argument', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(user_timeline|home_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)')); + array('method' => '(user_timeline|replies|mentions|show|destroy|friends|followers)')); // users diff --git a/lib/twitterapi.php b/lib/twitterapi.php index d199e4dee2..ac5c5b4239 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -502,7 +502,7 @@ class TwitterapiAction extends Action $enclosure = $entry['enclosures'][0]; $this->element('enclosure', array('url'=>$enclosure['url'],'type'=>$enclosure['mimetype'],'length'=>$enclosure['size']), null); } - + if(array_key_exists('tags', $entry)){ foreach($entry['tags'] as $tag){ $this->element('category', null,$tag); @@ -934,7 +934,7 @@ class TwitterapiAction extends Action return; } - function clientError($msg, $code = 400, $content_type = 'json') + function clientError($msg, $code = 400, $format = 'xml') { static $status = array(400 => 'Bad Request', @@ -967,20 +967,23 @@ class TwitterapiAction extends Action $status_string = $status[$code]; header('HTTP/1.1 '.$code.' '.$status_string); - if ($content_type == 'xml') { + if ($format == 'xml') { $this->init_document('xml'); $this->elementStart('hash'); $this->element('error', null, $msg); $this->element('request', null, $_SERVER['REQUEST_URI']); $this->elementEnd('hash'); $this->end_document('xml'); - } else { + } elseif ($format == 'json'){ $this->init_document('json'); $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); print(json_encode($error_array)); $this->end_document('json'); - } + } else { + // If user didn't request a useful format, throw a regular client error + throw new ClientException($msg, $code); + } } function init_twitter_rss() @@ -1063,6 +1066,39 @@ class TwitterapiAction extends Action } } + function getTargetUser($id) + { + if (empty($id)) { + + // Twitter supports these other ways of passing the user ID + if (is_numeric($this->arg('id'))) { + return User::staticGet($this->arg('id')); + } else if ($this->arg('id')) { + $nickname = common_canonical_nickname($this->arg('id')); + return User::staticGet('nickname', $nickname); + } else if ($this->arg('user_id')) { + // This is to ensure that a non-numeric user_id still + // overrides screen_name even if it doesn't get used + if (is_numeric($this->arg('user_id'))) { + return User::staticGet('id', $this->arg('user_id')); + } + } else if ($this->arg('screen_name')) { + $nickname = common_canonical_nickname($this->arg('screen_name')); + return User::staticGet('nickname', $nickname); + } else { + // Fall back to trying the currently authenticated user + return $this->auth_user; + } + + } else if (is_numeric($id)) { + return User::staticGet($id); + } else { + $nickname = common_canonical_nickname($id); + return User::staticGet('nickname', $nickname); + } + } + + function get_group($id, $apidata=null) { if (empty($id)) { @@ -1170,4 +1206,85 @@ class TwitterapiAction extends Action } } + function showBasicAuthHeader() + { + $this->basicAuthProcessHeader(); + + if (!isset($this->auth_user)) { + header('WWW-Authenticate: Basic realm="StatusNet API"'); + + // show error if the user clicks 'cancel' + + $this->showBasicAuthError(); + return false; + + } else { + $nickname = $this->auth_user; + $password = $this->auth_pw; + $this->auth_user = common_check_user($nickname, $password); + + if (empty($this->auth_user)) { + + // basic authentication failed + + list($proxy, $ip) = common_client_ip(); + common_log(LOG_WARNING, + "Failed API auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip."); + $this->showBasicAuthError(); + return false; + } + } + return true; + } + + function basicAuthProcessHeader() + { + 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 showBasicAuthError() + { + header('HTTP/1.1 401 Unauthorized'); + $msg = 'Could not authenticate you.'; + + if ($this->arg('format') == '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(); + } elseif ($this->arg('format') == '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"; + } + } + } From ed9ba9d945e4f50812022a7489fc8135f4e49846 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 24 Sep 2009 18:13:46 -0700 Subject: [PATCH 02/49] Reorganize, make bare auth work, output If-Modified-Since header --- actions/apifriendstimeline.php | 144 +++++++++++++++++++++------------ lib/twitterapi.php | 3 +- 2 files changed, 92 insertions(+), 55 deletions(-) diff --git a/actions/apifriendstimeline.php b/actions/apifriendstimeline.php index ea38ec022e..8c8d934164 100644 --- a/actions/apifriendstimeline.php +++ b/actions/apifriendstimeline.php @@ -36,6 +36,9 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; class ApifriendstimelineAction extends TwitterapiAction { + var $user = null; + var $notices = null; + /** * Take arguments for running * @@ -48,93 +51,120 @@ class ApifriendstimelineAction extends TwitterapiAction function prepare($args) { parent::prepare($args); - return true; - } + $this->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->max_id = (int)$this->arg('max_id', 0); + $this->since_id = (int)$this->arg('since_id', 0); + $this->since = $this->arg('since'); - function handle($args) { + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } - parent::handle($args); - common_debug(var_export($args, true)); + $this->user = $this->getTargetUser($this->arg('id')); - if ($this->requiresAuth()) { - if ($this->showBasicAuthHeader()) { - $this->showTimeline(); - } - } else { - $this->showTimeline(); - } - } - - function showTimeline() - { - common_debug('Auth user = ' . var_export($this->auth_user, true)); - - $user = $this->getTargetUser($this->arg('id')); - - if (empty($user)) { + if (empty($this->user)) { $this->clientError(_('No such user!'), 404, $this->arg('format')); return; } - $profile = $user->getProfile(); + $this->notices = $this->getNotices(); + + return true; + } + + function handle($args) { + parent::handle($args); + $this->showTimeline(); + } + + function showTimeline() + { + $profile = $this->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)); + 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); - } + $user->nickname, $sitename); switch($this->arg('format')) { - case 'xml': - $this->show_xml_timeline($notice); + case 'xml': + $this->show_xml_timeline($this->notices); break; - case 'rss': - $this->show_rss_timeline($notice, $title, $link, $subtitle); + case 'rss': + $this->show_rss_timeline($this->notices, $title, $link, $subtitle); break; - case 'atom': + case 'atom': $target_id = $this->arg('id'); if (isset($target_id)) { $selfuri = common_root_url() . - 'api/statuses/friends_timeline/' . - $target_id . '.atom'; + 'api/statuses/friends_timeline/' . + $target_id . '.atom'; } else { $selfuri = common_root_url() . - 'api/statuses/friends_timeline.atom'; + 'api/statuses/friends_timeline.atom'; } - $this->show_atom_timeline($notice, $title, $id, $link, - $subtitle, null, $selfuri); + $this->show_atom_timeline($this->notices, $title, $id, $link, + $subtitle, null, $selfuri); break; - case 'json': - $this->show_json_timeline($notice); + case 'json': + $this->show_json_timeline($this->notices); break; - default: + default: $this->clientError(_('API method not found!'), $code = 404); + break; + } + } + + 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; } function requiresAuth() { - return true; + // If the site is "private", all API methods except statusnet/config + // need authentication + + if (common_config('site', 'private')) { + return true; + } + + // bare auth: only needs auth if without an argument or query param specifying user id + + $id = $this->arg('id'); + $user_id = $this->arg('user_id'); + $screen_name = $this->arg('screen_name'); + + if (empty($id) && empty($user_id) && empty($screen_name)) { + return true; + } + + return false; } /** @@ -149,13 +179,21 @@ class ApifriendstimelineAction extends TwitterapiAction } /** - * When was this page last modified? + * When was this feed last modified? * */ function lastModified() { + if (empty($this->notices)) { + return null; + } + if (count($this->notices) == 0) { + return null; + } + + return strtotime($this->notices[0]->created); } } \ No newline at end of file diff --git a/lib/twitterapi.php b/lib/twitterapi.php index ac5c5b4239..959b0981a5 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -1098,7 +1098,6 @@ class TwitterapiAction extends Action } } - function get_group($id, $apidata=null) { if (empty($id)) { @@ -1206,7 +1205,7 @@ class TwitterapiAction extends Action } } - function showBasicAuthHeader() + function checkBasicAuthUser() { $this->basicAuthProcessHeader(); From de5ff19713a990af197330dd8e4314de465ffe76 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 25 Sep 2009 16:58:35 -0700 Subject: [PATCH 03/49] Moved basic auth stuff into its own classes --- actions/apifriendstimeline.php | 114 ++++++++++++---------------- lib/apiauth.php | 131 +++++++++++++++++++++++++++++++++ lib/apibareauth.php | 68 +++++++++++++++++ lib/router.php | 4 +- lib/twitterapi.php | 81 -------------------- 5 files changed, 247 insertions(+), 151 deletions(-) create mode 100644 lib/apiauth.php create mode 100644 lib/apibareauth.php diff --git a/actions/apifriendstimeline.php b/actions/apifriendstimeline.php index 8c8d934164..2eb00e23a6 100644 --- a/actions/apifriendstimeline.php +++ b/actions/apifriendstimeline.php @@ -31,9 +31,9 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/twitterapi.php'; +require_once INSTALLDIR.'/lib/apibareauth.php'; -class ApifriendstimelineAction extends TwitterapiAction +class ApiFriendsTimelineAction extends ApiBareAuthAction { var $user = null; @@ -52,33 +52,33 @@ class ApifriendstimelineAction extends TwitterapiAction { parent::prepare($args); - $this->page = (int)$this->arg('page', 1); + $this->page = (int)$this->arg('page', 1); $this->count = (int)$this->arg('count', 20); $this->max_id = (int)$this->arg('max_id', 0); $this->since_id = (int)$this->arg('since_id', 0); $this->since = $this->arg('since'); - if ($this->requiresAuth()) { + if ($this->requiresAuth()) { if ($this->checkBasicAuthUser() == false) { - return; - } - } + return; + } + } - $this->user = $this->getTargetUser($this->arg('id')); + $this->user = $this->getTargetUser($this->arg('id')); - if (empty($this->user)) { + if (empty($this->user)) { $this->clientError(_('No such user!'), 404, $this->arg('format')); return; } - $this->notices = $this->getNotices(); + $this->notices = $this->getNotices(); return true; } function handle($args) { - parent::handle($args); - $this->showTimeline(); + parent::handle($args); + $this->showTimeline(); } function showTimeline() @@ -89,82 +89,60 @@ class ApifriendstimelineAction extends TwitterapiAction $taguribase = common_config('integration', 'taguri'); $id = "tag:$taguribase:FriendsTimeline:" . $user->id; $link = common_local_url('all', - array('nickname' => $user->nickname)); + array('nickname' => $user->nickname)); $subtitle = sprintf(_('Updates from %1$s and friends on %2$s!'), - $user->nickname, $sitename); + $user->nickname, $sitename); switch($this->arg('format')) { - case 'xml': - $this->show_xml_timeline($this->notices); - break; - case 'rss': - $this->show_rss_timeline($this->notices, $title, $link, $subtitle); - break; - case 'atom': + case 'xml': + $this->show_xml_timeline($this->notices); + break; + case 'rss': + $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + break; + case 'atom': - $target_id = $this->arg('id'); + $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->show_atom_timeline($this->notices, $title, $id, $link, - $subtitle, null, $selfuri); - break; - case 'json': - $this->show_json_timeline($this->notices); - break; - default: - $this->clientError(_('API method not found!'), $code = 404); - break; + 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->show_atom_timeline($this->notices, $title, $id, $link, + $subtitle, null, $selfuri); + break; + case 'json': + $this->show_json_timeline($this->notices); + break; + default: + $this->clientError(_('API method not found!'), $code = 404); + break; } } function getNotices() { - $notices = array(); + $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); + $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); + $this->count, $this->since_id, + $this->max_id, $this->since); } - while ($notice->fetch()) { + while ($notice->fetch()) { $notices[] = clone($notice); } - return $notices; - } - - function requiresAuth() - { - // If the site is "private", all API methods except statusnet/config - // need authentication - - if (common_config('site', 'private')) { - return true; - } - - // bare auth: only needs auth if without an argument or query param specifying user id - - $id = $this->arg('id'); - $user_id = $this->arg('user_id'); - $screen_name = $this->arg('screen_name'); - - if (empty($id) && empty($user_id) && empty($screen_name)) { - return true; - } - - return false; + return $notices; } /** diff --git a/lib/apiauth.php b/lib/apiauth.php new file mode 100644 index 0000000000..501d3de10e --- /dev/null +++ b/lib/apiauth.php @@ -0,0 +1,131 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.php'; + +class ApiAuthAction extends TwitterapiAction +{ + /** + * Does this API resource require authentication? + * + * @return boolean true + */ + + function requiresAuth() + { + return true; + } + + function checkBasicAuthUser() + { + $this->basicAuthProcessHeader(); + + if (!isset($this->auth_user)) { + header('WWW-Authenticate: Basic realm="StatusNet API"'); + + // show error if the user clicks 'cancel' + + $this->showBasicAuthError(); + return false; + + } else { + $nickname = $this->auth_user; + $password = $this->auth_pw; + $this->auth_user = common_check_user($nickname, $password); + + if (empty($this->auth_user)) { + + // basic authentication failed + + list($proxy, $ip) = common_client_ip(); + common_log(LOG_WARNING, + "Failed API auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip."); + $this->showBasicAuthError(); + return false; + } + } + return true; + } + + function basicAuthProcessHeader() + { + 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 showBasicAuthError() + { + header('HTTP/1.1 401 Unauthorized'); + $msg = 'Could not authenticate you.'; + + if ($this->arg('format') == '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(); + } elseif ($this->arg('format') == '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"; + } + } + + +} \ No newline at end of file diff --git a/lib/apibareauth.php b/lib/apibareauth.php new file mode 100644 index 0000000000..8921cddca0 --- /dev/null +++ b/lib/apibareauth.php @@ -0,0 +1,68 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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'; + +class ApiBareAuthAction extends ApiAuthAction +{ + /** + * Does this API resource require authentication? + * + * @return boolean true or false + */ + + function requiresAuth() + { + // If the site is "private", all API methods except statusnet/config + // need authentication + + if (common_config('site', 'private')) { + return true; + } + + // check whether a user has been specified somehow + + $id = $this->arg('id'); + $user_id = $this->arg('user_id'); + $screen_name = $this->arg('screen_name'); + + if (empty($id) && empty($user_id) && empty($screen_name)) { + return true; + } + + return false; + } + +} \ No newline at end of file diff --git a/lib/router.php b/lib/router.php index 0e5fe3a54f..370fbe62b5 100644 --- a/lib/router.php +++ b/lib/router.php @@ -263,11 +263,11 @@ class Router // statuses API $m->connect('api/statuses/friends_timeline.:format', - array('action' => 'apifriendstimeline', + array('action' => 'ApiFriendsTimeline', 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/friends_timeline/:id.:format', - array('action' => 'apifriendstimeline', + array('action' => 'ApiFriendsTimeline', 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json|rss|atom)')); diff --git a/lib/twitterapi.php b/lib/twitterapi.php index 959b0981a5..5cf6666688 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -1205,85 +1205,4 @@ class TwitterapiAction extends Action } } - function checkBasicAuthUser() - { - $this->basicAuthProcessHeader(); - - if (!isset($this->auth_user)) { - header('WWW-Authenticate: Basic realm="StatusNet API"'); - - // show error if the user clicks 'cancel' - - $this->showBasicAuthError(); - return false; - - } else { - $nickname = $this->auth_user; - $password = $this->auth_pw; - $this->auth_user = common_check_user($nickname, $password); - - if (empty($this->auth_user)) { - - // basic authentication failed - - list($proxy, $ip) = common_client_ip(); - common_log(LOG_WARNING, - "Failed API auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip."); - $this->showBasicAuthError(); - return false; - } - } - return true; - } - - function basicAuthProcessHeader() - { - 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 showBasicAuthError() - { - header('HTTP/1.1 401 Unauthorized'); - $msg = 'Could not authenticate you.'; - - if ($this->arg('format') == '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(); - } elseif ($this->arg('format') == '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"; - } - } - } From dfa955bfda67ee9fd254e97abf9dc29f2b51a857 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 27 Sep 2009 14:11:12 -0700 Subject: [PATCH 04/49] - Output entity tag - More comments for function blocks --- actions/apifriendstimeline.php | 60 +++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/actions/apifriendstimeline.php b/actions/apifriendstimeline.php index 2eb00e23a6..dd89f44fe5 100644 --- a/actions/apifriendstimeline.php +++ b/actions/apifriendstimeline.php @@ -76,11 +76,27 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction 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(); @@ -124,6 +140,12 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction } } + /** + * Get notices + * + * @return array notices + */ + function getNotices() { $notices = array(); @@ -163,15 +185,37 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction function lastModified() { - if (empty($this->notices)) { - return null; + if (!empty($this->notices) && (count($this->notices) > 0)) { + return strtotime($this->notices[0]->created); } - if (count($this->notices) == 0) { - return null; - } - - return strtotime($this->notices[0]->created); + return null; } -} \ No newline at end of file + /** + * An entity tag for this page + * + * 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; + } + +} From 37bdc060c521203ff4e14a1a2b1d7fc59d1c2d4d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 27 Sep 2009 15:33:46 -0700 Subject: [PATCH 05/49] phpcs on apifriendstimeline.php, apiauth.php and apibareauth.php --- actions/apifriendstimeline.php | 110 +++++++++++++++++++++------------ lib/apiauth.php | 56 ++++++++++++++--- lib/apibareauth.php | 11 ++++ 3 files changed, 128 insertions(+), 49 deletions(-) diff --git a/actions/apifriendstimeline.php b/actions/apifriendstimeline.php index dd89f44fe5..dc280b3f3f 100644 --- a/actions/apifriendstimeline.php +++ b/actions/apifriendstimeline.php @@ -19,7 +19,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * - * @category Personal + * @category API * @package StatusNet * @author Zach Copley * @copyright 2009 StatusNet, Inc. @@ -33,6 +33,17 @@ if (!defined('STATUSNET')) { 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 Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + class ApiFriendsTimelineAction extends ApiBareAuthAction { @@ -86,7 +97,8 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction * @return void */ - function handle($args) { + function handle($args) + { parent::handle($args); $this->showTimeline(); } @@ -104,39 +116,45 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction $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); + $link = common_local_url( + 'all', array('nickname' => $user->nickname) + ); + $subtitle = sprintf( + _('Updates from %1$s and friends on %2$s!'), + $user->nickname, $sitename + ); switch($this->arg('format')) { - case 'xml': - $this->show_xml_timeline($this->notices); - break; - case 'rss': - $this->show_rss_timeline($this->notices, $title, $link, $subtitle); - break; - case 'atom': + case 'xml': + $this->show_xml_timeline($this->notices); + break; + case 'rss': + $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + break; + case 'atom': - $target_id = $this->arg('id'); + $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->show_atom_timeline($this->notices, $title, $id, $link, - $subtitle, null, $selfuri); - break; - case 'json': - $this->show_json_timeline($this->notices); - break; - default: - $this->clientError(_('API method not found!'), $code = 404); - break; + 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->show_atom_timeline( + $this->notices, $title, $id, $link, + $subtitle, null, $selfuri + ); + break; + case 'json': + $this->show_json_timeline($this->notices); + break; + default: + $this->clientError(_('API method not found!'), $code = 404); + break; } } @@ -151,13 +169,17 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction $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); + $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); + $notice = $this->user->noticesWithFriends( + ($this->page-1) * $this->count, + $this->count, $this->since_id, + $this->max_id, $this->since + ); } while ($notice->fetch()) { @@ -168,7 +190,9 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction } /** - * Is this page read-only? + * Is this action read only? + * + * @param array $args other arguments * * @return boolean true */ @@ -181,6 +205,7 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction /** * When was this feed last modified? * + * @return string datestamp of the latest notice in the stream */ function lastModified() @@ -193,7 +218,7 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction } /** - * An entity tag for this page + * 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 @@ -207,12 +232,15 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction $last = count($this->notices) - 1; - return implode(':', + return implode( + ':', array($this->arg('action'), common_language(), $this->user->id, strtotime($this->notices[0]->created), - strtotime($this->notices[$last]->created))) . '"'; + strtotime($this->notices[$last]->created)) + ) + . '"'; } return null; diff --git a/lib/apiauth.php b/lib/apiauth.php index 501d3de10e..c1976f964e 100644 --- a/lib/apiauth.php +++ b/lib/apiauth.php @@ -33,6 +33,16 @@ if (!defined('STATUSNET')) { require_once INSTALLDIR.'/lib/twitterapi.php'; +/** + * Actions extending this class will require auth + * + * @category API + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + class ApiAuthAction extends TwitterapiAction { /** @@ -46,6 +56,13 @@ class ApiAuthAction extends TwitterapiAction return true; } + /** + * Check for a user specified via HTTP basic auth. If there isn't + * one, try to get one by outputting the basic auth header. + * + * @return boolean true or false + */ + function checkBasicAuthUser() { $this->basicAuthProcessHeader(); @@ -68,8 +85,11 @@ class ApiAuthAction extends TwitterapiAction // basic authentication failed list($proxy, $ip) = common_client_ip(); - common_log(LOG_WARNING, - "Failed API auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip."); + common_log( + LOG_WARNING, + 'Failed API auth attempt, nickname = ' . + "$nickname, proxy = $proxy, ip = $ip." + ); $this->showBasicAuthError(); return false; } @@ -77,16 +97,28 @@ class ApiAuthAction extends TwitterapiAction return true; } + /** + * Read the HTTP headers and set the auth user. Decodes HTTP_AUTHORIZATION + * param to support basic auth when PHP is running in CGI mode. + * + * @return void + */ + function basicAuthProcessHeader() { - if (isset($_SERVER['AUTHORIZATION']) || isset($_SERVER['HTTP_AUTHORIZATION'])) { - $authorization_header = isset($_SERVER['HTTP_AUTHORIZATION'])? $_SERVER['HTTP_AUTHORIZATION'] : $_SERVER['AUTHORIZATION']; + 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')) { + } 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 @@ -94,6 +126,7 @@ class ApiAuthAction extends TwitterapiAction 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; @@ -104,6 +137,13 @@ class ApiAuthAction extends TwitterapiAction } } + /** + * Output an authentication error message. Use XML or JSON if one + * of those formats is specified, otherwise output plain text + * + * @return void + */ + function showBasicAuthError() { header('HTTP/1.1 401 Unauthorized'); @@ -119,7 +159,8 @@ class ApiAuthAction extends TwitterapiAction $this->endXML(); } elseif ($this->arg('format') == 'json') { header('Content-Type: application/json; charset=utf-8'); - $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); + $error_array = array('error' => $msg, + 'request' => $_SERVER['REQUEST_URI']); print(json_encode($error_array)); } else { header('Content-type: text/plain'); @@ -127,5 +168,4 @@ class ApiAuthAction extends TwitterapiAction } } - -} \ No newline at end of file +} diff --git a/lib/apibareauth.php b/lib/apibareauth.php index 8921cddca0..a99d450ecc 100644 --- a/lib/apibareauth.php +++ b/lib/apibareauth.php @@ -35,6 +35,17 @@ if (!defined('STATUSNET')) { require_once INSTALLDIR.'/lib/apiauth.php'; +/** + * Actions extending this class will require auth unless a target + * user ID has been specified + * + * @category API + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + class ApiBareAuthAction extends ApiAuthAction { /** From 99d2999b5cddb364177ab52bce01df71ffc656b3 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 27 Sep 2009 16:57:06 -0700 Subject: [PATCH 06/49] Broke out public_timeline and user_timeline into their own actions --- actions/apipublictimeline.php | 207 ++++++++++++++++++++++++++++ actions/apiusertimeline.php | 249 ++++++++++++++++++++++++++++++++++ 2 files changed, 456 insertions(+) create mode 100644 actions/apipublictimeline.php create mode 100644 actions/apiusertimeline.php diff --git a/actions/apipublictimeline.php b/actions/apipublictimeline.php new file mode 100644 index 0000000000..63cb0cbafb --- /dev/null +++ b/actions/apipublictimeline.php @@ -0,0 +1,207 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.php'; + +/** + * Returns the most recent notices (default 20) posted by everybody + * + * @category API + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class ApiPublicTimelineAction extends TwitterapiAction +{ + + var $notices = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + $this->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->max_id = (int)$this->arg('max_id', 0); + $this->since_id = (int)$this->arg('since_id', 0); + $this->since = $this->arg('since'); + + $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->arg('format')) { + case 'xml': + $this->show_xml_timeline($this->notices); + break; + case 'rss': + $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + break; + case 'atom': + $selfuri = common_root_url() . 'api/statuses/public_timeline.atom'; + $this->show_atom_timeline( + $this->notices, $title, $id, $link, + $subtitle, null, $selfuri + ); + break; + case 'json': + $this->show_json_timeline($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/apiusertimeline.php b/actions/apiusertimeline.php new file mode 100644 index 0000000000..1c69613136 --- /dev/null +++ b/actions/apiusertimeline.php @@ -0,0 +1,249 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class ApiUserTimelineAction extends ApiBareAuthAction +{ + + var $user = null; + var $notices = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + $this->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->max_id = (int)$this->arg('max_id', 0); + $this->since_id = (int)$this->arg('since_id', 0); + $this->since = $this->arg('since'); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->user = $this->getTargetUser($this->arg('id')); + + if (empty($this->user)) { + $this->clientError(_('No such user!'), 404, $this->arg('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->arg('format')) { + case 'xml': + $this->show_xml_timeline($this->notices); + break; + case 'rss': + $this->show_rss_timeline( + $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->show_atom_timeline( + $this->notices, $title, $id, $link, + $subtitle, $suplink, $selfuri + ); + break; + case 'json': + $this->show_json_timeline($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; + } + +} From eac388a3cb23ac35a2e9e5506938d34b408bae1d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 27 Sep 2009 17:17:03 -0700 Subject: [PATCH 07/49] Forgot to commit the routes for the new actions --- lib/router.php | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/router.php b/lib/router.php index d4d5b659cd..b9c6162226 100644 --- a/lib/router.php +++ b/lib/router.php @@ -266,6 +266,10 @@ class Router // statuses API + $m->connect('api/statuses/public_timeline.:format', + array('action' => 'ApiPublicTimeline', + 'format' => '(xml|json|rss|atom)')); + $m->connect('api/statuses/friends_timeline.:format', array('action' => 'ApiFriendsTimeline', 'format' => '(xml|json|rss|atom)')); @@ -275,18 +279,36 @@ class Router 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json|rss|atom)')); + $m->connect('api/statuses/user_timeline.:format', + array('action' => 'ApiUserTimeline', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statuses/user_timeline/:id.:format', + array('action' => 'ApiUserTimeline', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statuses/mentions.:format', + array('action' => 'ApiMentions', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statuses/mentions/:id.:format', + array('action' => 'ApiMentions', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json|rss|atom)')); + $m->connect('api/statuses/home_timeline', array('action' => 'apifriendstimeline')); $m->connect('api/statuses/:method', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(public_timeline|user_timeline|update|replies|mentions|show|friends|followers|featured)(\.(atom|rss|xml|json))?')); + array('method' => '(update|replies|show|friends|followers|featured)(\.(atom|rss|xml|json))?')); $m->connect('api/statuses/:method/:argument', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(user_timeline|replies|mentions|show|destroy|friends|followers)')); + array('method' => '(replies|show|destroy|friends|followers)')); // users From 44dd8f833dca4ab0b076a7fc7d16fdfed317b41f Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 27 Sep 2009 17:17:57 -0700 Subject: [PATCH 08/49] Broke mentions API method out into its own action --- actions/apimentions.php | 234 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 actions/apimentions.php diff --git a/actions/apimentions.php b/actions/apimentions.php new file mode 100644 index 0000000000..2b2e27f20d --- /dev/null +++ b/actions/apimentions.php @@ -0,0 +1,234 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class ApiMentionsAction extends ApiBareAuthAction +{ + + var $user = null; + var $notices = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + $this->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->max_id = (int)$this->arg('max_id', 0); + $this->since_id = (int)$this->arg('since_id', 0); + $this->since = $this->arg('since'); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->user = $this->getTargetUser($this->arg('id')); + + if (empty($this->user)) { + $this->clientError(_('No such user!'), 404, $this->arg('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->arg('format')) { + case 'xml': + $this->show_xml_timeline($this->notices); + break; + case 'rss': + $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + break; + case 'atom': + $selfuri = common_root_url() . + ltrim($_SERVER['QUERY_STRING'], 'p='); + $this->show_atom_timeline( + $this->notices, $title, $id, $link, $subtitle, + null, $selfuri + ); + break; + case 'json': + $this->show_json_timeline($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; + } + +} From d392cbed7d4ba2f280211177eb99830bd3b61b04 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 27 Sep 2009 17:23:11 -0700 Subject: [PATCH 09/49] Route aliases: replies -> mentions and home_timeline -> friends_timeline --- lib/router.php | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/router.php b/lib/router.php index b9c6162226..91cdd2cf80 100644 --- a/lib/router.php +++ b/lib/router.php @@ -278,6 +278,14 @@ class Router array('action' => 'ApiFriendsTimeline', 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json|rss|atom)')); + $m->connect('api/statuses/home_timeline.:format', + array('action' => 'ApiFriendsTimeline', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statuses/home_timeline/:id.:format', + array('action' => 'ApiFriendsTimeline', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/user_timeline.:format', array('action' => 'ApiUserTimeline', @@ -297,18 +305,27 @@ class Router 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json|rss|atom)')); + $m->connect('api/statuses/replies.:format', + array('action' => 'ApiMentions', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statuses/replies/:id.:format', + array('action' => 'ApiMentions', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json|rss|atom)')); + $m->connect('api/statuses/home_timeline', array('action' => 'apifriendstimeline')); $m->connect('api/statuses/:method', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(update|replies|show|friends|followers|featured)(\.(atom|rss|xml|json))?')); + array('method' => '(update|show|friends|followers|featured)(\.(atom|rss|xml|json))?')); $m->connect('api/statuses/:method/:argument', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(replies|show|destroy|friends|followers)')); + array('method' => '(show|destroy|friends|followers)')); // users From f3820cc85d53c9885744deb76d4b48cd1ec8f7e9 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 27 Sep 2009 17:27:42 -0700 Subject: [PATCH 10/49] Fix nickname in feed title --- actions/apifriendstimeline.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/actions/apifriendstimeline.php b/actions/apifriendstimeline.php index dc280b3f3f..5205160163 100644 --- a/actions/apifriendstimeline.php +++ b/actions/apifriendstimeline.php @@ -113,15 +113,15 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction { $profile = $this->user->getProfile(); $sitename = common_config('site', 'name'); - $title = sprintf(_("%s and friends"), $user->nickname); + $title = sprintf(_("%s and friends"), $this->user->nickname); $taguribase = common_config('integration', 'taguri'); - $id = "tag:$taguribase:FriendsTimeline:" . $user->id; + $id = "tag:$taguribase:FriendsTimeline:" . $this->user->id; $link = common_local_url( - 'all', array('nickname' => $user->nickname) + 'all', array('nickname' => $this->user->nickname) ); $subtitle = sprintf( _('Updates from %1$s and friends on %2$s!'), - $user->nickname, $sitename + $this->user->nickname, $sitename ); switch($this->arg('format')) { From e307adfbfc44e653ee2b5b94dcf7eabdc8ffe0df Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 30 Sep 2009 10:22:26 -0700 Subject: [PATCH 11/49] New actions for /statuses/friends and /statuses/followers + social graph methods --- actions/apifollowers.php | 85 +++++++++++ actions/apifriends.php | 85 +++++++++++ actions/apisubscriptions.php | 275 +++++++++++++++++++++++++++++++++++ lib/apiauth.php | 3 + lib/router.php | 55 ++++--- lib/twitterapi.php | 2 - 6 files changed, 479 insertions(+), 26 deletions(-) create mode 100644 actions/apifollowers.php create mode 100644 actions/apifriends.php create mode 100644 actions/apisubscriptions.php diff --git a/actions/apifollowers.php b/actions/apifollowers.php new file mode 100644 index 0000000000..30e3b2d1bf --- /dev/null +++ b/actions/apifollowers.php @@ -0,0 +1,85 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class ApiFollowersAction 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/apifriends.php b/actions/apifriends.php new file mode 100644 index 0000000000..12751a6419 --- /dev/null +++ b/actions/apifriends.php @@ -0,0 +1,85 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class ApiFriendsAction 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/apisubscriptions.php b/actions/apisubscriptions.php new file mode 100644 index 0000000000..78dcd722dd --- /dev/null +++ b/actions/apisubscriptions.php @@ -0,0 +1,275 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $page = null; + var $count = null; + var $user = null; + var $profiles = null; + var $format = 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->page = (int)$this->arg('page', 1); + $this->tag = $this->arg('tag'); + $this->format = $this->arg('format'); + + // 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); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return false; + } + } + + $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->init_document($this->format); + + if (isset($this->ids_only)) { + $this->showIds(); + } else { + $this->showProfiles(isset($this->lite) ? false : true); + } + + $this->end_document($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->show_profile( + $profile, + $this->format, + null, + $include_statuses + ); + } + $this->elementEnd('users'); + break; + case 'json': + $arrays = array(); + foreach ($this->profiles as $profile) { + $arrays[] = $this->twitter_user_array( + $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/lib/apiauth.php b/lib/apiauth.php index c1976f964e..f0b4b6bf7f 100644 --- a/lib/apiauth.php +++ b/lib/apiauth.php @@ -45,6 +45,9 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; class ApiAuthAction extends TwitterapiAction { + + var $auth_user = null; + /** * Does this API resource require authentication? * diff --git a/lib/router.php b/lib/router.php index 91cdd2cf80..b3bb240d9a 100644 --- a/lib/router.php +++ b/lib/router.php @@ -314,18 +314,33 @@ class Router 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json|rss|atom)')); - $m->connect('api/statuses/home_timeline', - array('action' => 'apifriendstimeline')); + $m->connect('api/statuses/friends.:format', + array('action' => 'ApiFriends', + 'format' => '(xml|json)')); + + $m->connect('api/statuses/friends/:id.:format', + array('action' => 'ApiFriends', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/statuses/followers.:format', + array('action' => 'ApiFollowers', + 'format' => '(xml|json)')); + + $m->connect('api/statuses/followers/:id.:format', + array('action' => 'ApiFollowers', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); $m->connect('api/statuses/:method', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(update|show|friends|followers|featured)(\.(atom|rss|xml|json))?')); + array('method' => '(update|show|featured)(\.(atom|rss|xml|json))?')); $m->connect('api/statuses/:method/:argument', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(show|destroy|friends|followers)')); + array('method' => '(show|destroy)')); // users @@ -380,29 +395,21 @@ class Router // Social graph - $m->connect('api/friends/ids/:argument', - array('action' => 'api', - 'apiaction' => 'statuses', - 'method' => 'friendsIDs')); + $m->connect('api/friends/ids/:id.:format', + array('action' => 'apiFriends', + 'ids_only' => true)); - foreach (array('xml', 'json') as $e) { - $m->connect('api/friends/ids.'.$e, - array('action' => 'api', - 'apiaction' => 'statuses', - 'method' => 'friendsIDs.'.$e)); - } + $m->connect('api/followers/ids/:id.:format', + array('action' => 'apiFollowers', + 'ids_only' => true)); - $m->connect('api/followers/ids/:argument', - array('action' => 'api', - 'apiaction' => 'statuses', - 'method' => 'followersIDs')); + $m->connect('api/friends/ids.:format', + array('action' => 'apiFriends', + 'ids_only' => true)); - foreach (array('xml', 'json') as $e) { - $m->connect('api/followers/ids.'.$e, - array('action' => 'api', - 'apiaction' => 'statuses', - 'method' => 'followersIDs.'.$e)); - } + $m->connect('api/followers/ids.:format', + array('action' => 'apiFollowers', + 'ids_only' => true)); // account diff --git a/lib/twitterapi.php b/lib/twitterapi.php index 5cf6666688..6014a340eb 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -24,8 +24,6 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { class TwitterapiAction extends Action { - var $auth_user; - /** * Initialization. * From 1e7939cc4857db1109df40979bd475d4c0da48e9 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 30 Sep 2009 10:27:54 -0700 Subject: [PATCH 12/49] Left opening double quotes off Etag --- actions/apifriendstimeline.php | 2 +- actions/apimentions.php | 2 +- actions/apipublictimeline.php | 2 +- actions/apiusertimeline.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/actions/apifriendstimeline.php b/actions/apifriendstimeline.php index 5205160163..1e88d1c2b4 100644 --- a/actions/apifriendstimeline.php +++ b/actions/apifriendstimeline.php @@ -232,7 +232,7 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction $last = count($this->notices) - 1; - return implode( + return '"' . implode( ':', array($this->arg('action'), common_language(), diff --git a/actions/apimentions.php b/actions/apimentions.php index 2b2e27f20d..43e93a9c63 100644 --- a/actions/apimentions.php +++ b/actions/apimentions.php @@ -217,7 +217,7 @@ class ApiMentionsAction extends ApiBareAuthAction $last = count($this->notices) - 1; - return implode( + return '"' . implode( ':', array($this->arg('action'), common_language(), diff --git a/actions/apipublictimeline.php b/actions/apipublictimeline.php index 63cb0cbafb..2be979e6dc 100644 --- a/actions/apipublictimeline.php +++ b/actions/apipublictimeline.php @@ -191,7 +191,7 @@ class ApiPublicTimelineAction extends TwitterapiAction $last = count($this->notices) - 1; - return implode( + return '"' . implode( ':', array($this->arg('action'), common_language(), diff --git a/actions/apiusertimeline.php b/actions/apiusertimeline.php index 1c69613136..44d69415bd 100644 --- a/actions/apiusertimeline.php +++ b/actions/apiusertimeline.php @@ -232,7 +232,7 @@ class ApiUserTimelineAction extends ApiBareAuthAction $last = count($this->notices) - 1; - return implode( + return '"' . implode( ':', array($this->arg('action'), common_language(), From 34ba2d03e94d3708a68166a8eae248152691f628 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 30 Sep 2009 10:30:06 -0700 Subject: [PATCH 13/49] Fix header comment --- actions/apifollowers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/apifollowers.php b/actions/apifollowers.php index 30e3b2d1bf..b216cced7e 100644 --- a/actions/apifollowers.php +++ b/actions/apifollowers.php @@ -2,7 +2,7 @@ /** * StatusNet, the distributed open-source microblogging tool * - * Show a user's followers (subscriptions) + * Show a user's followers (subscribers) * * PHP version 5 * From 524c2794c954346a00d7bf4cd58a6742bc005707 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 30 Sep 2009 17:02:04 -0700 Subject: [PATCH 14/49] Declare some more variables; instance variable for format --- actions/apifriendstimeline.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/actions/apifriendstimeline.php b/actions/apifriendstimeline.php index 1e88d1c2b4..be0cf758c2 100644 --- a/actions/apifriendstimeline.php +++ b/actions/apifriendstimeline.php @@ -47,8 +47,13 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; class ApiFriendsTimelineAction extends ApiBareAuthAction { - var $user = null; - var $notices = null; + var $user = null; + var $notices = null; + var $count = null; + var $max_id = null; + var $since_id = null; + var $since = null; + var $format = null; /** * Take arguments for running @@ -68,6 +73,7 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction $this->max_id = (int)$this->arg('max_id', 0); $this->since_id = (int)$this->arg('since_id', 0); $this->since = $this->arg('since'); + $this->format = $this->arg('format'); if ($this->requiresAuth()) { if ($this->checkBasicAuthUser() == false) { @@ -78,7 +84,7 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction $this->user = $this->getTargetUser($this->arg('id')); if (empty($this->user)) { - $this->clientError(_('No such user!'), 404, $this->arg('format')); + $this->clientError(_('No such user!'), 404, $this->format); return; } @@ -124,7 +130,7 @@ class ApiFriendsTimelineAction extends ApiBareAuthAction $this->user->nickname, $sitename ); - switch($this->arg('format')) { + switch($this->format) { case 'xml': $this->show_xml_timeline($this->notices); break; From a3901e0e243d42fb75162a063c10b77fddd7dfe5 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 30 Sep 2009 17:06:46 -0700 Subject: [PATCH 15/49] New action for /statuses/show --- actions/apishow.php | 196 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 actions/apishow.php diff --git a/actions/apishow.php b/actions/apishow.php new file mode 100644 index 0000000000..3d0b7b6e3a --- /dev/null +++ b/actions/apishow.php @@ -0,0 +1,196 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.php'; + +/** + * Returns the notice specified by id as a Twitter-style status and inline user + * + * @category API + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class ApiShowAction extends TwitterapiAction +{ + + var $notice_id = null; + var $notice = null; + var $format = 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->format = $this->arg('format'); + $this->notice = Notice::staticGet((int)$this->notice_id); + + return true; + } + + /** + * Handle the request + * + * Just show the notices + * + * @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 timeline of notices + * + * @return void + */ + + function showNotice() + { + if (!empty($this->notice)) { + if ($this->format == 'xml') { + $this->show_single_xml_status($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->notices->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; + } + +} From 8b8e0c95af8efe656c3c7a67153117ba8128456e Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 30 Sep 2009 17:08:52 -0700 Subject: [PATCH 16/49] Add route for /statuses/show --- actions/apishow.php | 10 +++++----- lib/router.php | 11 ++++++++++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/actions/apishow.php b/actions/apishow.php index 3d0b7b6e3a..d17cc8c95d 100644 --- a/actions/apishow.php +++ b/actions/apishow.php @@ -83,7 +83,7 @@ class ApiShowAction extends TwitterapiAction /** * Handle the request * - * Just show the notices + * Check the format and show the notice * * @param array $args $_REQUEST data (unused) * @@ -103,7 +103,7 @@ class ApiShowAction extends TwitterapiAction } /** - * Show the timeline of notices + * Show the notice * * @return void */ @@ -125,14 +125,14 @@ class ApiShowAction extends TwitterapiAction if (!empty($deleted)) { $this->clientError( - _('Status deleted.'), - 410, + _('Status deleted.'), + 410, $this->format ); } else { $this->clientError( _('No status with that ID found.'), - 404, + 404, $this->format ); } diff --git a/lib/router.php b/lib/router.php index b3bb240d9a..972db4c9df 100644 --- a/lib/router.php +++ b/lib/router.php @@ -332,10 +332,19 @@ class Router 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json)')); + $m->connect('api/statuses/show.:format', + array('action' => 'ApiShow', + 'format' => '(xml|json)')); + + $m->connect('api/statuses/show/:id.:format', + array('action' => 'ApiShow', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + $m->connect('api/statuses/:method', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(update|show|featured)(\.(atom|rss|xml|json))?')); + array('method' => '(update|featured)(\.(atom|rss|xml|json))?')); $m->connect('api/statuses/:method/:argument', array('action' => 'api', From c5f33cc6c26cc10dbcf2f1d3104875ad694f2256 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 30 Sep 2009 17:11:22 -0700 Subject: [PATCH 17/49] Fix: last modified header wasn't showing --- actions/apishow.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/apishow.php b/actions/apishow.php index d17cc8c95d..952c7f593b 100644 --- a/actions/apishow.php +++ b/actions/apishow.php @@ -161,7 +161,7 @@ class ApiShowAction extends TwitterapiAction function lastModified() { if (!empty($this->notice)) { - return strtotime($this->notices->created); + return strtotime($this->notice->created); } return null; From b0ddb971e61bd98250c41e653ab2e649a9b08926 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 1 Oct 2009 16:15:52 -0700 Subject: [PATCH 18/49] New action for /statuses/update --- actions/apiupdate.php | 240 ++++++++++++++++++++++++++++++++++++++++++ lib/router.php | 9 +- 2 files changed, 244 insertions(+), 5 deletions(-) create mode 100644 actions/apiupdate.php diff --git a/actions/apiupdate.php b/actions/apiupdate.php new file mode 100644 index 0000000000..9ce208f656 --- /dev/null +++ b/actions/apiupdate.php @@ -0,0 +1,240 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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'; + +/** + * Updates the authenticating user's status (posts a notice). + * + * @category API + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class ApiUpdateAction extends ApiAuthAction +{ + + var $user = null; + var $source = null; + var $status = null; + var $in_reply_to_status_id = null; + var $format = 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); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return false; + } + } + + $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->format = $this->arg('format'); + + $this->in_reply_to_status_id + = intval($this->trimmed('in_reply_to_status_id')); + + return true; + } + + /** + * Handle the request + * + * Just show the notices + * + * @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->show_single_xml_status($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/lib/router.php b/lib/router.php index 972db4c9df..1ea06afe08 100644 --- a/lib/router.php +++ b/lib/router.php @@ -341,15 +341,14 @@ class Router 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json)')); - $m->connect('api/statuses/:method', - array('action' => 'api', - 'apiaction' => 'statuses'), - array('method' => '(update|featured)(\.(atom|rss|xml|json))?')); + $m->connect('api/statuses/update.:format', + array('action' => 'ApiUpdate', + 'format' => '(xml|json)')); $m->connect('api/statuses/:method/:argument', array('action' => 'api', 'apiaction' => 'statuses'), - array('method' => '(show|destroy)')); + array('method' => 'destroy')); // users From 9a1dbee0fdd1f586512e4517a5abb7898501bc11 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 1 Oct 2009 17:35:28 -0700 Subject: [PATCH 19/49] A new action for /statuses/destroy --- actions/apidestroy.php | 152 +++++++++++++++++++++++++++++++++++++++++ actions/apiupdate.php | 4 +- lib/router.php | 15 ++-- 3 files changed, 164 insertions(+), 7 deletions(-) create mode 100644 actions/apidestroy.php diff --git a/actions/apidestroy.php b/actions/apidestroy.php new file mode 100644 index 0000000000..a3b6bf65e8 --- /dev/null +++ b/actions/apidestroy.php @@ -0,0 +1,152 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class ApiDestroyAction extends ApiAuthAction +{ + + var $user = null; + var $status = null; + var $format = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return false; + } + } + + $this->user = $this->auth_user; + $this->notice_id = (int)$this->trimmed('id'); + + if (empty($notice_id)) { + $this->notice_id = (int)$this->arg('id'); + } + + $this->format = $this->arg('format'); + $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->show_single_xml_status($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->show_single_xml_status($this->notice); + } elseif ($this->format == 'json') { + $this->show_single_json_status($this->notice); + } + } + } + +} diff --git a/actions/apiupdate.php b/actions/apiupdate.php index 9ce208f656..04a38f3f87 100644 --- a/actions/apiupdate.php +++ b/actions/apiupdate.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apibareauth.php'; +require_once INSTALLDIR.'/lib/apiauth.php'; /** * Updates the authenticating user's status (posts a notice). @@ -109,7 +109,7 @@ class ApiUpdateAction extends ApiAuthAction /** * Handle the request * - * Just show the notices + * Make a new notice for the update, save it, and show it * * @param array $args $_REQUEST data (unused) * diff --git a/lib/router.php b/lib/router.php index 3de4e322f9..5c9513f570 100644 --- a/lib/router.php +++ b/lib/router.php @@ -342,17 +342,22 @@ class Router $m->connect('api/statuses/show/:id.:format', array('action' => 'ApiShow', - 'id' => '[a-zA-Z0-9]+', + 'id' => '[0-9]+', 'format' => '(xml|json)')); $m->connect('api/statuses/update.:format', array('action' => 'ApiUpdate', 'format' => '(xml|json)')); - $m->connect('api/statuses/:method/:argument', - array('action' => 'api', - 'apiaction' => 'statuses'), - array('method' => 'destroy')); + $m->connect('api/statuses/destroy.:format', + array('action' => 'ApiDestroy', + 'format' => '(xml|json)')); + + $m->connect('api/statuses/destroy/:id.:format', + array('action' => 'ApiDestroy', + 'id' => '[0-9]+', + 'format' => '(xml|json)')); + // users From 1e0c36afb5c265eff1d72331b44239e35f5226ed Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 1 Oct 2009 18:19:59 -0700 Subject: [PATCH 20/49] Renamed and moved stuff around to better match Twitter's API organization --- ...{apidestroy.php => apistatusesdestroy.php} | 2 +- actions/{apishow.php => apistatusesshow.php} | 2 +- .../{apiupdate.php => apistatusesupdate.php} | 2 +- ...ndstimeline.php => apitimelinefriends.php} | 2 +- ...pimentions.php => apitimelinementions.php} | 2 +- ...blictimeline.php => apitimelinepublic.php} | 2 +- ...piusertimeline.php => apitimelineuser.php} | 2 +- ...{apifollowers.php => apiuserfollowers.php} | 2 +- .../{apifriends.php => apiuserfriends.php} | 2 +- actions/twitapistatuses.php | 606 ------------------ lib/router.php | 40 +- 11 files changed, 29 insertions(+), 635 deletions(-) rename actions/{apidestroy.php => apistatusesdestroy.php} (98%) rename actions/{apishow.php => apistatusesshow.php} (98%) rename actions/{apiupdate.php => apistatusesupdate.php} (99%) rename actions/{apifriendstimeline.php => apitimelinefriends.php} (99%) rename actions/{apimentions.php => apitimelinementions.php} (99%) rename actions/{apipublictimeline.php => apitimelinepublic.php} (98%) rename actions/{apiusertimeline.php => apitimelineuser.php} (99%) rename actions/{apifollowers.php => apiuserfollowers.php} (97%) rename actions/{apifriends.php => apiuserfriends.php} (97%) delete mode 100644 actions/twitapistatuses.php diff --git a/actions/apidestroy.php b/actions/apistatusesdestroy.php similarity index 98% rename from actions/apidestroy.php rename to actions/apistatusesdestroy.php index a3b6bf65e8..ae0f4c4532 100644 --- a/actions/apidestroy.php +++ b/actions/apistatusesdestroy.php @@ -43,7 +43,7 @@ require_once INSTALLDIR.'/lib/apiauth.php'; * @link http://status.net/ */ -class ApiDestroyAction extends ApiAuthAction +class ApiStatusesDestroyAction extends ApiAuthAction { var $user = null; diff --git a/actions/apishow.php b/actions/apistatusesshow.php similarity index 98% rename from actions/apishow.php rename to actions/apistatusesshow.php index 952c7f593b..55eea2356d 100644 --- a/actions/apishow.php +++ b/actions/apistatusesshow.php @@ -43,7 +43,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; * @link http://status.net/ */ -class ApiShowAction extends TwitterapiAction +class ApiStatusesShowAction extends TwitterapiAction { var $notice_id = null; diff --git a/actions/apiupdate.php b/actions/apistatusesupdate.php similarity index 99% rename from actions/apiupdate.php rename to actions/apistatusesupdate.php index 04a38f3f87..fb12785593 100644 --- a/actions/apiupdate.php +++ b/actions/apistatusesupdate.php @@ -43,7 +43,7 @@ require_once INSTALLDIR.'/lib/apiauth.php'; * @link http://status.net/ */ -class ApiUpdateAction extends ApiAuthAction +class ApiStatusesUpdateAction extends ApiAuthAction { var $user = null; diff --git a/actions/apifriendstimeline.php b/actions/apitimelinefriends.php similarity index 99% rename from actions/apifriendstimeline.php rename to actions/apitimelinefriends.php index be0cf758c2..65bbb5a74a 100644 --- a/actions/apifriendstimeline.php +++ b/actions/apitimelinefriends.php @@ -44,7 +44,7 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; * @link http://status.net/ */ -class ApiFriendsTimelineAction extends ApiBareAuthAction +class ApiTimelineFriendsAction extends ApiBareAuthAction { var $user = null; diff --git a/actions/apimentions.php b/actions/apitimelinementions.php similarity index 99% rename from actions/apimentions.php rename to actions/apitimelinementions.php index 43e93a9c63..93c6da3073 100644 --- a/actions/apimentions.php +++ b/actions/apitimelinementions.php @@ -43,7 +43,7 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; * @link http://status.net/ */ -class ApiMentionsAction extends ApiBareAuthAction +class ApiTimelineMentionsAction extends ApiBareAuthAction { var $user = null; diff --git a/actions/apipublictimeline.php b/actions/apitimelinepublic.php similarity index 98% rename from actions/apipublictimeline.php rename to actions/apitimelinepublic.php index 2be979e6dc..10bde6f37d 100644 --- a/actions/apipublictimeline.php +++ b/actions/apitimelinepublic.php @@ -43,7 +43,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; * @link http://status.net/ */ -class ApiPublicTimelineAction extends TwitterapiAction +class ApiTimelinePublicAction extends TwitterapiAction { var $notices = null; diff --git a/actions/apiusertimeline.php b/actions/apitimelineuser.php similarity index 99% rename from actions/apiusertimeline.php rename to actions/apitimelineuser.php index 44d69415bd..c4d02bc622 100644 --- a/actions/apiusertimeline.php +++ b/actions/apitimelineuser.php @@ -45,7 +45,7 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; * @link http://status.net/ */ -class ApiUserTimelineAction extends ApiBareAuthAction +class ApiTimelineUserAction extends ApiBareAuthAction { var $user = null; diff --git a/actions/apifollowers.php b/actions/apiuserfollowers.php similarity index 97% rename from actions/apifollowers.php rename to actions/apiuserfollowers.php index b216cced7e..5c0243449b 100644 --- a/actions/apifollowers.php +++ b/actions/apiuserfollowers.php @@ -45,7 +45,7 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; * @link http://status.net/ */ -class ApiFollowersAction extends ApiSubscriptionsAction +class ApiUserFollowersAction extends ApiSubscriptionsAction { /** * Get the user's subscribers (followers) as an array of profiles diff --git a/actions/apifriends.php b/actions/apiuserfriends.php similarity index 97% rename from actions/apifriends.php rename to actions/apiuserfriends.php index 12751a6419..8a42e36b98 100644 --- a/actions/apifriends.php +++ b/actions/apiuserfriends.php @@ -45,7 +45,7 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; * @link http://status.net/ */ -class ApiFriendsAction extends ApiSubscriptionsAction +class ApiUserFriendsAction extends ApiSubscriptionsAction { /** * Get the user's subscriptions (friends) as an array of profiles diff --git a/actions/twitapistatuses.php b/actions/twitapistatuses.php deleted file mode 100644 index 87043b1821..0000000000 --- a/actions/twitapistatuses.php +++ /dev/null @@ -1,606 +0,0 @@ -. - */ - -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 home_timeline($args, $apidata) - { - call_user_func(array($this, 'friends_timeline'), $args, $apidata); - } - - 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); - - 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/lib/router.php b/lib/router.php index 5c9513f570..357c702247 100644 --- a/lib/router.php +++ b/lib/router.php @@ -271,90 +271,90 @@ class Router // statuses API $m->connect('api/statuses/public_timeline.:format', - array('action' => 'ApiPublicTimeline', + array('action' => 'ApiTimelinePublic', 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/friends_timeline.:format', - array('action' => 'ApiFriendsTimeline', + array('action' => 'ApiTimelineFriends', 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/friends_timeline/:id.:format', - array('action' => 'ApiFriendsTimeline', + array('action' => 'ApiTimelineFriends', 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/home_timeline.:format', - array('action' => 'ApiFriendsTimeline', + array('action' => 'ApiTimelineFriends', 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/home_timeline/:id.:format', - array('action' => 'ApiFriendsTimeline', + array('action' => 'ApiTimelineFriends', 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/user_timeline.:format', - array('action' => 'ApiUserTimeline', + array('action' => 'ApiTimelineUser', 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/user_timeline/:id.:format', - array('action' => 'ApiUserTimeline', + array('action' => 'ApiTimelineUser', 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/mentions.:format', - array('action' => 'ApiMentions', + array('action' => 'ApiTimelineMentions', 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/mentions/:id.:format', - array('action' => 'ApiMentions', + array('action' => 'ApiTimelineMentions', 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/replies.:format', - array('action' => 'ApiMentions', + array('action' => 'ApiTimelineMentions', 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/replies/:id.:format', - array('action' => 'ApiMentions', + array('action' => 'ApiTimelineMentions', 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json|rss|atom)')); $m->connect('api/statuses/friends.:format', - array('action' => 'ApiFriends', + array('action' => 'ApiUserFriends', 'format' => '(xml|json)')); $m->connect('api/statuses/friends/:id.:format', - array('action' => 'ApiFriends', + array('action' => 'ApiUserFriends', 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json)')); $m->connect('api/statuses/followers.:format', - array('action' => 'ApiFollowers', + array('action' => 'ApiUserFollowers', 'format' => '(xml|json)')); $m->connect('api/statuses/followers/:id.:format', - array('action' => 'ApiFollowers', + array('action' => 'ApiUserFollowers', 'id' => '[a-zA-Z0-9]+', 'format' => '(xml|json)')); $m->connect('api/statuses/show.:format', - array('action' => 'ApiShow', + array('action' => 'ApiStatusesShow', 'format' => '(xml|json)')); $m->connect('api/statuses/show/:id.:format', - array('action' => 'ApiShow', + array('action' => 'ApiStatusesShow', 'id' => '[0-9]+', 'format' => '(xml|json)')); $m->connect('api/statuses/update.:format', - array('action' => 'ApiUpdate', + array('action' => 'ApiStatusesUpdate', 'format' => '(xml|json)')); $m->connect('api/statuses/destroy.:format', - array('action' => 'ApiDestroy', + array('action' => 'ApiStatusesDestroy', 'format' => '(xml|json)')); $m->connect('api/statuses/destroy/:id.:format', - array('action' => 'ApiDestroy', + array('action' => 'ApiStatusesDestroy', 'id' => '[0-9]+', 'format' => '(xml|json)')); From eaef9b689ab41eed23eb74841ed5038066c485a3 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 2 Oct 2009 10:31:13 -0700 Subject: [PATCH 21/49] New action for /users/show --- actions/apiusershow.php | 126 +++++++++++++++++++++++++++++++++++++++ actions/twitapiusers.php | 80 ------------------------- lib/router.php | 8 +-- 3 files changed, 130 insertions(+), 84 deletions(-) create mode 100644 actions/apiusershow.php delete mode 100644 actions/twitapiusers.php diff --git a/actions/apiusershow.php b/actions/apiusershow.php new file mode 100644 index 0000000000..2e2ceab41b --- /dev/null +++ b/actions/apiusershow.php @@ -0,0 +1,126 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.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 Zach Copley + * @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 TwitterApiAction +{ + + var $format = null; + var $user = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + $this->format = $this->arg('format'); + + $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->twitter_user_array($this->user->getProfile(), true); + + if ($this->format == 'xml') { + $this->init_document('xml'); + $this->show_twitter_xml_user($twitter_user); + $this->end_document('xml'); + } elseif ($this->format == 'json') { + $this->init_document('json'); + $this->show_json_objects($twitter_user); + $this->end_document('json'); + } + + } + +} diff --git a/actions/twitapiusers.php b/actions/twitapiusers.php deleted file mode 100644 index 703fa6754f..0000000000 --- a/actions/twitapiusers.php +++ /dev/null @@ -1,80 +0,0 @@ -. - */ - -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/lib/router.php b/lib/router.php index 357c702247..57f9864bc5 100644 --- a/lib/router.php +++ b/lib/router.php @@ -361,10 +361,10 @@ class Router // users - $m->connect('api/users/:method/:argument', - array('action' => 'api', - 'apiaction' => 'users'), - array('method' => 'show(\.(xml|json))?')); + $m->connect('api/users/show/:id.:format', + array('action' => 'ApiUserShow', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); $m->connect('api/users/:method', array('action' => 'api', From daa8b47306626b2b26b2d48a54449cd7394fc22e Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 2 Oct 2009 17:23:48 -0700 Subject: [PATCH 22/49] New actions for direct messaging through the API --- actions/apidirectmessage.php | 389 +++++++++++++++++++++++++++++ actions/apidirectmessagenew.php | 192 ++++++++++++++ actions/twitapidirect_messages.php | 305 ---------------------- lib/router.php | 34 +-- lib/twitterapi.php | 194 ++++++++------ 5 files changed, 707 insertions(+), 407 deletions(-) create mode 100644 actions/apidirectmessage.php create mode 100644 actions/apidirectmessagenew.php delete mode 100644 actions/twitapidirect_messages.php diff --git a/actions/apidirectmessage.php b/actions/apidirectmessage.php new file mode 100644 index 0000000000..87ae44d7a5 --- /dev/null +++ b/actions/apidirectmessage.php @@ -0,0 +1,389 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $messages = null; + var $page = null; + var $count = null; + var $max_id = null; + var $since_id = null; + var $since = 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); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->user = $this->auth_user; + + if (empty($this->user)) { + $this->clientError(_('No such user!'), 404, $this->format); + return; + } + + $this->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->max_id = (int)$this->arg('max_id', 0); + $this->since_id = (int)$this->arg('since_id', 0); + $this->since = $this->arg('since'); + + $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->format = $this->arg('format'); + + $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->init_document('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->end_document('xml'); + } + + /** + * Shows a list of direct messages as a JSON encoded array + * + * @return void + */ + + function showJsonDirectMessages() + { + $this->init_document('json'); + + $dmsgs = array(); + + foreach ($this->messages as $m) { + $dm_array = $this->directMessageArray($m); + array_push($dmsgs, $dm_array); + } + + $this->show_json_objects($dmsgs); + $this->end_document('json'); + } + + /** + * Shows a list of direct messages as RSS items + * + * @return void + */ + + function showRssDirectMessages() + { + $this->init_document('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->show_twitter_rss_item($entry); + } + + $this->end_twitter_rss(); + } + + /** + * Shows a list of direct messages as Atom entries + * + * @return void + */ + + function showAtomDirectMessages() + { + $this->init_document('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->end_document('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 0000000000..d836409ae0 --- /dev/null +++ b/actions/apidirectmessagenew.php @@ -0,0 +1,192 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $source = null; + var $user = 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); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $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); + } + + $this->format = $this->arg('format'); + + 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/twitapidirect_messages.php b/actions/twitapidirect_messages.php deleted file mode 100644 index 08b8f4e9c1..0000000000 --- a/actions/twitapidirect_messages.php +++ /dev/null @@ -1,305 +0,0 @@ -. - */ - -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/lib/router.php b/lib/router.php index 57f9864bc5..75abf58ab8 100644 --- a/lib/router.php +++ b/lib/router.php @@ -358,7 +358,6 @@ class Router 'id' => '[0-9]+', 'format' => '(xml|json)')); - // users $m->connect('api/users/show/:id.:format', @@ -373,30 +372,19 @@ class Router // direct messages - foreach (array('xml', 'json') as $e) { - $m->connect('api/direct_messages/new.'.$e, - array('action' => 'api', - 'apiaction' => 'direct_messages', - 'method' => 'create.'.$e)); - } - foreach (array('xml', 'json', 'rss', 'atom') as $e) { - $m->connect('api/direct_messages.'.$e, - array('action' => 'api', - 'apiaction' => 'direct_messages', - 'method' => 'direct_messages.'.$e)); - } + $m->connect('api/direct_messages.:format', + array('action' => 'ApiDirectMessage', + 'format' => '(xml|json|rss|atom)')); - foreach (array('xml', 'json', 'rss', 'atom') as $e) { - $m->connect('api/direct_messages/sent.'.$e, - array('action' => 'api', - 'apiaction' => 'direct_messages', - 'method' => 'sent.'.$e)); - } + $m->connect('api/direct_messages/sent.:format', + array('action' => 'ApiDirectMessage', + 'format' => '(xml|json|rss|atom)', + 'sent' => true)); - $m->connect('api/direct_messages/destroy/:argument', - array('action' => 'api', - 'apiaction' => 'direct_messages')); + $m->connect('api/direct_messages/new.:format', + array('action' => 'ApiDirectMessageNew', + 'format' => '(xml|json)')); // friendships @@ -410,7 +398,7 @@ class Router 'apiaction' => 'friendships'), array('method' => '(show|exists)(\.(xml|json))')); - // Social graph + // Social graph $m->connect('api/friends/ids/:id.:format', array('action' => 'apiFriends', diff --git a/lib/twitterapi.php b/lib/twitterapi.php index 708738832b..b2104fddd6 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -322,51 +322,6 @@ class TwitterapiAction extends Action return $entry; } - function twitter_rss_dmsg_array($message) - { - - $entry = array(); - - $entry['title'] = sprintf('Message from %s to %s', - $message->getFrom()->nickname, $message->getTo()->nickname); - - $entry['content'] = common_xml_safe_str(trim($message->content)); - $entry['link'] = common_local_url('showmessage', array('message' => $message->id)); - $entry['published'] = common_date_iso8601($message->created); - - $taguribase = common_config('integration', 'taguri'); - - $entry['id'] = "tag:$taguribase,:$entry[link]"; - $entry['updated'] = $entry['published']; - $entry['author'] = $message->getFrom()->getBestName(); - - # RSS Item specific - $entry['description'] = $entry['content']; - $entry['pubDate'] = common_date_rfc2822($message->created); - $entry['guid'] = $entry['link']; - - return $entry; - } - - function twitter_dmsg_array($message) - { - $twitter_dm = array(); - - $from_profile = $message->getFrom(); - $to_profile = $message->getTo(); - - $twitter_dm['id'] = $message->id; - $twitter_dm['sender_id'] = $message->from_profile; - $twitter_dm['text'] = trim($message->content); - $twitter_dm['recipient_id'] = $message->to_profile; - $twitter_dm['created_at'] = $this->date_twitter($message->created); - $twitter_dm['sender_screen_name'] = $from_profile->nickname; - $twitter_dm['recipient_screen_name'] = $to_profile->nickname; - $twitter_dm['sender'] = $this->twitter_user_array($from_profile, false); - $twitter_dm['recipient'] = $this->twitter_user_array($to_profile, false); - - return $twitter_dm; - } function twitter_relationship_array($source, $target) { @@ -531,40 +486,6 @@ class TwitterapiAction extends Action $this->end_document('json'); } - function show_single_xml_dmsg($message) - { - $this->init_document('xml'); - $dmsg = $this->twitter_dmsg_array($message); - $this->show_twitter_xml_dmsg($dmsg); - $this->end_document('xml'); - } - - function show_single_json_dmsg($message) - { - $this->init_document('json'); - $dmsg = $this->twitter_dmsg_array($message); - $this->show_json_objects($dmsg); - $this->end_document('json'); - } - - function show_twitter_xml_dmsg($twitter_dm) - { - $this->elementStart('direct_message'); - foreach($twitter_dm as $element => $value) { - switch ($element) { - case 'sender': - case 'recipient': - $this->show_twitter_xml_user($value, $element); - break; - case 'text': - $this->element($element, null, common_xml_safe_str($value)); - break; - default: - $this->element($element, null, $value); - } - } - $this->elementEnd('direct_message'); - } function show_xml_timeline($notice) { @@ -685,6 +606,121 @@ class TwitterapiAction extends Action $this->end_twitter_rss(); } + + function showTwitterAtomEntry($entry) + { + $this->elementStart('entry'); + $this->element('title', null, $entry['title']); + $this->element('content', array('type' => 'html'), $entry['content']); + $this->element('id', null, $entry['id']); + $this->element('published', null, $entry['published']); + $this->element('updated', null, $entry['updated']); + $this->element('link', array('type' => 'text/html', + 'href' => $entry['link'], + 'rel' => 'alternate')); + $this->element('link', array('type' => $entry['avatar-type'], + 'href' => $entry['avatar'], + 'rel' => 'image')); + $this->elementStart('author'); + + $this->element('name', null, $entry['author-name']); + $this->element('uri', null, $entry['author-uri']); + + $this->elementEnd('author'); + $this->elementEnd('entry'); + } + + function showXmlDirectMessage($dm) + { + $this->elementStart('direct_message'); + foreach($dm as $element => $value) { + switch ($element) { + case 'sender': + case 'recipient': + $this->show_twitter_xml_user($value, $element); + break; + case 'text': + $this->element($element, null, common_xml_safe_str($value)); + break; + default: + $this->element($element, null, $value); + break; + } + } + $this->elementEnd('direct_message'); + } + + function directMessageArray($message) + { + $dmsg = array(); + + $from_profile = $message->getFrom(); + $to_profile = $message->getTo(); + + $dmsg['id'] = $message->id; + $dmsg['sender_id'] = $message->from_profile; + $dmsg['text'] = trim($message->content); + $dmsg['recipient_id'] = $message->to_profile; + $dmsg['created_at'] = $this->date_twitter($message->created); + $dmsg['sender_screen_name'] = $from_profile->nickname; + $dmsg['recipient_screen_name'] = $to_profile->nickname; + $dmsg['sender'] = $this->twitter_user_array($from_profile, false); + $dmsg['recipient'] = $this->twitter_user_array($to_profile, false); + + return $dmsg; + } + + function rssDirectMessageArray($message) + { + $entry = array(); + + $from = $message->getFrom(); + + $entry['title'] = sprintf('Message from %s to %s', + $from->nickname, $message->getTo()->nickname); + + $entry['content'] = common_xml_safe_str($message->rendered); + $entry['link'] = common_local_url('showmessage', array('message' => $message->id)); + $entry['published'] = common_date_iso8601($message->created); + + $taguribase = common_config('integration', 'taguri'); + + $entry['id'] = "tag:$taguribase:$entry[link]"; + $entry['updated'] = $entry['published']; + + $entry['author-name'] = $from->getBestName(); + $entry['author-uri'] = $from->homepage; + + $avatar = $from->getAvatar(AVATAR_STREAM_SIZE); + + $entry['avatar'] = (!empty($avatar)) ? $avatar->url : Avatar::defaultImage(AVATAR_STREAM_SIZE); + $entry['avatar-type'] = (!empty($avatar)) ? $avatar->mediatype : 'image/png'; + + // RSS item specific + + $entry['description'] = $entry['content']; + $entry['pubDate'] = common_date_rfc2822($message->created); + $entry['guid'] = $entry['link']; + + return $entry; + } + + function showSingleXmlDirectMessage($message) + { + $this->init_document('xml'); + $dmsg = $this->directMessageArray($message); + $this->showXmlDirectMessage($dmsg); + $this->end_document('xml'); + } + + function showSingleJsonDirectMessage($message) + { + $this->init_document('json'); + $dmsg = $this->directMessageArray($message); + $this->show_json_objects($dmsg); + $this->end_document('json'); + } + function show_atom_groups($group, $title, $id, $link, $subtitle=null, $selfuri=null) { From 4ed8055f86d3e3c517a9e367607f60d595b77f37 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 5 Oct 2009 09:57:59 -0700 Subject: [PATCH 23/49] New actions for managing subscriptions (friendships) --- actions/apifriendshipscreate.php | 134 ++++++++++++++++ actions/apifriendshipsdestroy.php | 136 ++++++++++++++++ actions/apifriendshipsexists.php | 128 +++++++++++++++ actions/apifriendshipsshow.php | 175 +++++++++++++++++++++ actions/twitapifriendships.php | 250 ------------------------------ 5 files changed, 573 insertions(+), 250 deletions(-) create mode 100644 actions/apifriendshipscreate.php create mode 100644 actions/apifriendshipsdestroy.php create mode 100644 actions/apifriendshipsexists.php create mode 100644 actions/apifriendshipsshow.php delete mode 100644 actions/twitapifriendships.php diff --git a/actions/apifriendshipscreate.php b/actions/apifriendshipscreate.php new file mode 100644 index 0000000000..d691b5b4f8 --- /dev/null +++ b/actions/apifriendshipscreate.php @@ -0,0 +1,134 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $user = null; + var $other = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->format = $this->arg('format'); + $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 (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->init_document($this->format); + $this->show_profile($this->other, $this->format); + $this->end_document($this->format); + } + +} diff --git a/actions/apifriendshipsdestroy.php b/actions/apifriendshipsdestroy.php new file mode 100644 index 0000000000..d97c5aa6db --- /dev/null +++ b/actions/apifriendshipsdestroy.php @@ -0,0 +1,136 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $user = null; + var $other = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->format = $this->arg('format'); + $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 (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->init_document($this->format); + $this->show_profile($this->other, $this->format); + $this->end_document($this->format); + } + +} diff --git a/actions/apifriendshipsexists.php b/actions/apifriendshipsexists.php new file mode 100644 index 0000000000..3d6e7448de --- /dev/null +++ b/actions/apifriendshipsexists.php @@ -0,0 +1,128 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.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 Zach Copley + * @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 TwitterApiAction +{ + + var $format = null; + 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); + + $this->format = $this->arg('format'); + + $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->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; + } + } + +} diff --git a/actions/apifriendshipsshow.php b/actions/apifriendshipsshow.php new file mode 100644 index 0000000000..d35825a433 --- /dev/null +++ b/actions/apifriendshipsshow.php @@ -0,0 +1,175 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $user = null; + 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); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->format = $this->arg('format'); + + $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->twitter_relationship_array($this->source, $this->target); + + switch ($this->format) { + 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/twitapifriendships.php b/actions/twitapifriendships.php deleted file mode 100644 index eea8945c39..0000000000 --- a/actions/twitapifriendships.php +++ /dev/null @@ -1,250 +0,0 @@ -. - */ - -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; - } - } - -} From ee207ffd8be4a7178d06ff7c6928dba3714146ec Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 5 Oct 2009 10:04:35 -0700 Subject: [PATCH 24/49] Routes for friendships actions --- lib/router.php | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/lib/router.php b/lib/router.php index 75abf58ab8..5ee9396571 100644 --- a/lib/router.php +++ b/lib/router.php @@ -388,17 +388,33 @@ class Router // friendships - $m->connect('api/friendships/:method/:argument', - array('action' => 'api', - 'apiaction' => 'friendships'), - array('method' => '(create|destroy)')); + $m->connect('api/friendships/show.:format', + array('action' => 'ApiFriendshipsShow', + 'format' => '(xml|json)')); - $m->connect('api/friendships/:method', - array('action' => 'api', - 'apiaction' => 'friendships'), - array('method' => '(show|exists)(\.(xml|json))')); + $m->connect('api/friendships/exists.:format', + array('action' => 'ApiFriendshipsExists', + 'format' => '(xml|json)')); - // Social graph + $m->connect('api/friendships/create.:format', + array('action' => 'ApiFriendshipsCreate', + 'format' => '(xml|json)')); + + $m->connect('api/friendships/destroy.:format', + array('action' => 'ApiFriendshipsDestroy', + 'format' => '(xml|json)')); + + $m->connect('api/friendships/create/:id.:format', + array('action' => 'ApiFriendshipsCreate', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/friendships/destroy/:id.:format', + array('action' => 'ApiFriendshipsDestroy', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + // Social graph $m->connect('api/friends/ids/:id.:format', array('action' => 'apiFriends', From 62d1475df1c85c63f6d0dc4628a912c7666c2d21 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 5 Oct 2009 13:25:34 -0700 Subject: [PATCH 25/49] Add in a check for proper format --- actions/apifriendshipscreate.php | 9 +++++++++ actions/apifriendshipsdestroy.php | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/actions/apifriendshipscreate.php b/actions/apifriendshipscreate.php index d691b5b4f8..969fc12820 100644 --- a/actions/apifriendshipscreate.php +++ b/actions/apifriendshipscreate.php @@ -101,6 +101,15 @@ class ApiFriendshipsCreateAction extends ApiAuthAction 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.'), diff --git a/actions/apifriendshipsdestroy.php b/actions/apifriendshipsdestroy.php index d97c5aa6db..ef864c4db8 100644 --- a/actions/apifriendshipsdestroy.php +++ b/actions/apifriendshipsdestroy.php @@ -101,6 +101,15 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction 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.'), From dd0d90723142d8042991f998f2b0c355d47638b5 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 5 Oct 2009 13:50:01 -0700 Subject: [PATCH 26/49] New actions for favorites via the API --- actions/apifavoritecreate.php | 175 +++++++++++++++++++++ actions/apifavoritedestroy.php | 154 +++++++++++++++++++ actions/apitimelinefavorites.php | 255 +++++++++++++++++++++++++++++++ actions/twitapifavorites.php | 216 -------------------------- lib/router.php | 30 ++-- 5 files changed, 600 insertions(+), 230 deletions(-) create mode 100644 actions/apifavoritecreate.php create mode 100644 actions/apifavoritedestroy.php create mode 100644 actions/apitimelinefavorites.php delete mode 100644 actions/twitapifavorites.php diff --git a/actions/apifavoritecreate.php b/actions/apifavoritecreate.php new file mode 100644 index 0000000000..e45603c6a2 --- /dev/null +++ b/actions/apifavoritecreate.php @@ -0,0 +1,175 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $user = null; + var $notice = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->format = $this->arg('format'); + $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->show_single_xml_status($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 0000000000..a70d5c79b1 --- /dev/null +++ b/actions/apifavoritedestroy.php @@ -0,0 +1,154 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $user = null; + var $notice = null; + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->format = $this->arg('format'); + $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->show_single_xml_status($this->notice); + } elseif ($this->format == 'json') { + $this->show_single_json_status($this->notice); + } + } + +} diff --git a/actions/apitimelinefavorites.php b/actions/apitimelinefavorites.php new file mode 100644 index 0000000000..9ccee5cfac --- /dev/null +++ b/actions/apitimelinefavorites.php @@ -0,0 +1,255 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $user = null; + var $notices = null; + var $format = null; + var $page = null; + var $count = null; + var $max_id = null; + var $since_id = null; + var $since = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->max_id = (int)$this->arg('max_id', 0); + $this->since_id = (int)$this->arg('since_id', 0); + $this->since = $this->arg('since'); + $this->format = $this->arg('format'); + + $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->show_xml_timeline($this->notices); + break; + case 'rss': + $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + break; + case 'atom': + $selfuri = common_root_url() . + ltrim($_SERVER['QUERY_STRING'], 'p='); + $this->show_atom_timeline( + $this->notices, $title, $id, $link, $subtitle, + null, $selfuri + ); + break; + case 'json': + $this->show_json_timeline($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/twitapifavorites.php b/actions/twitapifavorites.php deleted file mode 100644 index f8943fe2dd..0000000000 --- a/actions/twitapifavorites.php +++ /dev/null @@ -1,216 +0,0 @@ -. - */ - -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/lib/router.php b/lib/router.php index 5ee9396571..8e6db88809 100644 --- a/lib/router.php +++ b/lib/router.php @@ -440,22 +440,24 @@ class Router // favorites - $m->connect('api/favorites/:method/:argument', - array('action' => 'api', - 'apiaction' => 'favorites', - array('method' => '(create|destroy)'))); + $m->connect('api/favorites.:format', + array('action' => 'ApiTimelineFavorites', + 'format' => '(xml|json|rss|atom)')); - $m->connect('api/favorites/:argument', - array('action' => 'api', - 'apiaction' => 'favorites', - 'method' => 'favorites')); + $m->connect('api/favorites/:id.:format', + array('action' => 'ApiTimelineFavorites', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xmljson|rss|atom)')); - foreach (array('xml', 'json', 'rss', 'atom') as $e) { - $m->connect('api/favorites.'.$e, - array('action' => 'api', - 'apiaction' => 'favorites', - 'method' => 'favorites.'.$e)); - } + $m->connect('api/favorites/create/:id.:format', + array('action' => 'ApiFavoriteCreate', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/favorites/destroy/:id.:format', + array('action' => 'ApiFavoriteDestroy', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); // notifications From 475bdf6fba3ee8081f3726f98ecd3a50fdda305e Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 5 Oct 2009 17:10:30 -0700 Subject: [PATCH 27/49] New actions for the account methods we have implemented --- actions/apiaccountratelimitstatus.php | 132 ++++++++++++++++++++++++ actions/apiaccountverifycredentials.php | 104 +++++++++++++++++++ actions/twitapiaccount.php | 127 ----------------------- lib/router.php | 13 ++- 4 files changed, 246 insertions(+), 130 deletions(-) create mode 100644 actions/apiaccountratelimitstatus.php create mode 100644 actions/apiaccountverifycredentials.php delete mode 100644 actions/twitapiaccount.php diff --git a/actions/apiaccountratelimitstatus.php b/actions/apiaccountratelimitstatus.php new file mode 100644 index 0000000000..3c6c3e714d --- /dev/null +++ b/actions/apiaccountratelimitstatus.php @@ -0,0 +1,132 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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: 100 hits left. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 +{ + var $format = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return false; + } + } + + $this->format = $this->arg('format'); + return true; + } + + /** + * 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->init_document($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->end_document($this->format); + } + +} + diff --git a/actions/apiaccountverifycredentials.php b/actions/apiaccountverifycredentials.php new file mode 100644 index 0000000000..b9c9bf0f72 --- /dev/null +++ b/actions/apiaccountverifycredentials.php @@ -0,0 +1,104 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 +{ + var $format = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return false; + } + } + + $this->format = $this->arg('format'); + return true; + } + + /** + * 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(); + $action_obj->prepare($args); + $action_obj->handle($args); + break; + default: + header('Content-Type: text/html; charset=utf-8'); + print 'Authorized'; + } + + } + +} diff --git a/actions/twitapiaccount.php b/actions/twitapiaccount.php deleted file mode 100644 index 93c8443c9f..0000000000 --- a/actions/twitapiaccount.php +++ /dev/null @@ -1,127 +0,0 @@ -. - */ - -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/lib/router.php b/lib/router.php index 8e6db88809..6541d69f14 100644 --- a/lib/router.php +++ b/lib/router.php @@ -434,9 +434,16 @@ class Router // account - $m->connect('api/account/:method', - array('action' => 'api', - 'apiaction' => 'account')); + $m->connect('api/account/verify_credentials.:format', + array('action' => 'ApiAccountVerifyCredentials')); + + // special case where verify_credentials is called w/out a format + + $m->connect('api/account/verify_credentials', + array('action' => 'ApiAccountVerifyCredentials')); + + $m->connect('api/account/rate_limit_status.:format', + array('action' => 'ApiAccountRateLimitStatus')); // favorites From f7688bec0d7683f0bad1bbb9806a7a6f5a261901 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 5 Oct 2009 17:11:32 -0700 Subject: [PATCH 28/49] Better Twitter date output --- lib/twitterapi.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/twitterapi.php b/lib/twitterapi.php index b2104fddd6..2141194df6 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -884,12 +884,12 @@ class TwitterapiAction extends Action $this->end_document('xml'); } - // Anyone know what date format this is? - // Twitter's dates look like this: "Mon Jul 14 23:52:38 +0000 2008" -- Zach function date_twitter($dt) { - $t = strtotime($dt); - return date("D M d H:i:s O Y", $t); + $dateStr = date('d F Y H:i:s', strtotime($dt)); + $d = new DateTime($dateStr, new DateTimeZone('UTC')); + $d->setTimezone(new DateTimeZone(common_timezone())); + return $d->format('D M d H:i:s O Y'); } // XXX: Candidate for a general utility method somewhere? From 8d284ca82c1e33a102ef4cb7aa150dd54d876ec7 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 6 Oct 2009 15:39:13 -0700 Subject: [PATCH 29/49] New action for tag timelines in the API --- actions/apitimelinetag.php | 212 +++++++++++++++++++++++++++++++++++++ actions/twitapitags.php | 113 -------------------- lib/router.php | 10 +- 3 files changed, 215 insertions(+), 120 deletions(-) create mode 100644 actions/apitimelinetag.php delete mode 100644 actions/twitapitags.php diff --git a/actions/apitimelinetag.php b/actions/apitimelinetag.php new file mode 100644 index 0000000000..1627763798 --- /dev/null +++ b/actions/apitimelinetag.php @@ -0,0 +1,212 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.php'; + +/** + * Returns the 20 most recent notices tagged by a given tag + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 TwitterapiAction +{ + + var $notices = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + $this->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->tag = $this->arg('tag'); + $this->format = $this->arg('format'); + + $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->show_xml_timeline($this->notices); + break; + case 'rss': + $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + break; + case 'atom': + $selfuri = common_root_url() . + 'api/statusnet/tags/timeline/' . + $this->tag . '.atom'; + $this->show_atom_timeline( + $this->notices, $title, $id, $link, + $subtitle, null, $selfuri + ); + break; + case 'json': + $this->show_json_timeline($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/twitapitags.php b/actions/twitapitags.php deleted file mode 100644 index 0bcc55d378..0000000000 --- a/actions/twitapitags.php +++ /dev/null @@ -1,113 +0,0 @@ -. - * - * @category Twitter - * @package StatusNet - * @author Craig Andrews - * @author Zach Copley - * @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 - * @author Zach Copley - * @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/lib/router.php b/lib/router.php index 6541d69f14..03210ce98c 100644 --- a/lib/router.php +++ b/lib/router.php @@ -532,13 +532,9 @@ class Router 'apiaction' => 'groups')); // Tags - $m->connect('api/statusnet/tags/:method/:argument', - array('action' => 'api', - 'apiaction' => 'tags')); - - $m->connect('api/statusnet/tags/:method', - array('action' => 'api', - 'apiaction' => 'tags')); + $m->connect('api/statusnet/tags/timeline/:tag.:format', + array('action' => 'ApiTimelineTag', + 'format' => '(xmljson|rss|atom)')); // search $m->connect('api/search.atom', array('action' => 'twitapisearchatom')); From 85af1c92adef021a91ed3618b748435248bf1023 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 6 Oct 2009 17:25:10 -0700 Subject: [PATCH 30/49] phpcs cleanup --- actions/apitimelinetag.php | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/actions/apitimelinetag.php b/actions/apitimelinetag.php index 1627763798..2a23bb72a2 100644 --- a/actions/apitimelinetag.php +++ b/actions/apitimelinetag.php @@ -97,10 +97,15 @@ class ApiTimelineTagAction extends TwitterapiAction { $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); + $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; @@ -115,9 +120,14 @@ class ApiTimelineTagAction extends TwitterapiAction $selfuri = common_root_url() . 'api/statusnet/tags/timeline/' . $this->tag . '.atom'; - $this->show_atom_timeline( - $this->notices, $title, $id, $link, - $subtitle, null, $selfuri + $this->show_atom_timeline( + $this->notices, + $title, + $id, + $link, + $subtitle, + null, + $selfuri ); break; case 'json': From 170b009865e3fcb183d562f47d66986b0e397f2d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 6 Oct 2009 17:26:45 -0700 Subject: [PATCH 31/49] New action for group timelines via API --- actions/apitimelinegroup.php | 233 +++++++++++++++++++++++++++++++++++ lib/router.php | 15 +-- lib/twitterapi.php | 2 +- 3 files changed, 240 insertions(+), 10 deletions(-) create mode 100644 actions/apitimelinegroup.php diff --git a/actions/apitimelinegroup.php b/actions/apitimelinegroup.php new file mode 100644 index 0000000000..11f73eeedb --- /dev/null +++ b/actions/apitimelinegroup.php @@ -0,0 +1,233 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.php'; + +/** + * Returns the most recent notices (default 20) posted to the group specified by ID + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 TwitterapiAction +{ + + 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->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->max_id = (int)$this->arg('max_id', 0); + $this->since_id = (int)$this->arg('since_id', 0); + $this->since = $this->arg('since'); + + $this->group = $this->getTargetGroup($this->arg('id')); + + $this->format = $this->arg('format'); + $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->show_xml_timeline($this->notices); + break; + case 'rss': + $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + break; + case 'atom': + $selfuri = common_root_url() . + 'api/statusnet/groups/timeline/' . + $this->group->nickname . '.atom'; + $this->show_atom_timeline( + $this->notices, + $title, + $id, + $link, + $subtitle, + null, + $selfuri + ); + break; + case 'json': + $this->show_json_timeline($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/lib/router.php b/lib/router.php index 03210ce98c..dbe2be0bb4 100644 --- a/lib/router.php +++ b/lib/router.php @@ -501,6 +501,12 @@ class Router // Groups //'list' has to be handled differently, as php will not allow a method to be named 'list' + + $m->connect('api/statusnet/groups/timeline/:id.:format', + array('action' => 'ApiTimelineGroup', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xmljson|rss|atom)')); + $m->connect('api/statusnet/groups/list/:argument', array('action' => 'api', 'method' => 'list_groups', @@ -518,15 +524,6 @@ class Router 'apiaction' => 'statuses'), array('method' => '(list_all|)(\.(atom|rss|xml|json))?')); - $m->connect('api/statuses/:method/:argument', - array('action' => 'api', - 'apiaction' => 'statuses'), - array('method' => '(user_timeline|home_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)')); - - $m->connect('api/statusnet/groups/:method/:argument', - array('action' => 'api', - 'apiaction' => 'groups')); - $m->connect('api/statusnet/groups/:method', array('action' => 'api', 'apiaction' => 'groups')); diff --git a/lib/twitterapi.php b/lib/twitterapi.php index 2141194df6..5cd88628bb 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -1142,7 +1142,7 @@ class TwitterapiAction extends Action } } - function get_group($id, $apidata=null) + function getTargetGroup($id) { if (empty($id)) { From 08de0f1ebdabdce561ce863bdec219a913e61d26 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 7 Oct 2009 17:20:08 -0700 Subject: [PATCH 32/49] New individual actions for dealing with groups via API --- actions/apigroupismember.php | 125 +++++++++ actions/apigroupjoin.php | 167 ++++++++++++ actions/apigroupleave.php | 153 +++++++++++ actions/apigrouplist.php | 237 +++++++++++++++++ actions/apigrouplistall.php | 215 ++++++++++++++++ actions/apigroupmembership.php | 200 +++++++++++++++ actions/apigroupshow.php | 148 +++++++++++ actions/twitapigroups.php | 453 --------------------------------- lib/router.php | 65 +++-- lib/twitterapi.php | 7 +- 10 files changed, 1296 insertions(+), 474 deletions(-) create mode 100644 actions/apigroupismember.php create mode 100644 actions/apigroupjoin.php create mode 100644 actions/apigroupleave.php create mode 100644 actions/apigrouplist.php create mode 100644 actions/apigrouplistall.php create mode 100644 actions/apigroupmembership.php create mode 100644 actions/apigroupshow.php delete mode 100644 actions/twitapigroups.php diff --git a/actions/apigroupismember.php b/actions/apigroupismember.php new file mode 100644 index 0000000000..facc58174e --- /dev/null +++ b/actions/apigroupismember.php @@ -0,0 +1,125 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $user = null; + var $group = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->user = $this->getTargetUser(null); + $this->group = $this->getTargetGroup(null); + $this->format = $this->arg('format'); + + 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->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!'), + 400, + $this->format + ); + break; + } + } + +} diff --git a/actions/apigroupjoin.php b/actions/apigroupjoin.php new file mode 100644 index 0000000000..c00d594631 --- /dev/null +++ b/actions/apigroupjoin.php @@ -0,0 +1,167 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $user = null; + var $group = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->user = $this->auth_user; + $this->group = $this->getTargetGroup($this->arg('id')); + + $this->format = $this->arg('format'); + + 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->show_single_json_group($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 0000000000..568b04b7cf --- /dev/null +++ b/actions/apigroupleave.php @@ -0,0 +1,153 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $user = null; + var $group = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->user = $this->auth_user; + $this->group = $this->getTargetGroup($this->arg('id')); + + $this->format = $this->arg('format'); + + 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->show_single_json_group($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 0000000000..84b7fc1c8c --- /dev/null +++ b/actions/apigrouplist.php @@ -0,0 +1,237 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $user = null; + var $page = null; + var $count = null; + var $max_id = null; + var $since_id = null; + var $since = null; + var $groups = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->max_id = (int)$this->arg('max_id', 0); + $this->since_id = (int)$this->arg('since_id', 0); + $this->since = $this->arg('since'); + + $this->user = $this->getTargetUser($id); + $this->format = $this->arg('format'); + $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->show_xml_groups($this->groups); + break; + case 'rss': + $this->show_rss_groups($this->groups, $title, $link, $subtitle); + break; + case 'atom': + $selfuri = common_root_url() . 'api/statusnet/groups/list/' . + $this->user->id . '.atom'; + $this->show_atom_groups( + $this->groups, + $title, + $id, + $link, + $subtitle, + $selfuri + ); + break; + case 'json': + $this->show_json_groups($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 0000000000..b1964d8005 --- /dev/null +++ b/actions/apigrouplistall.php @@ -0,0 +1,215 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.php'; + +/** + * Returns of the lastest 20 groups for the site + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 TwitterApiAction +{ + var $format = null; + var $page = null; + var $count = null; + var $max_id = null; + var $since_id = null; + var $since = null; + var $groups = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + $this->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->max_id = (int)$this->arg('max_id', 0); + $this->since_id = (int)$this->arg('since_id', 0); + $this->since = $this->arg('since'); + + $this->user = $this->getTargetUser($id); + $this->format = $this->arg('format'); + $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->show_xml_groups($this->groups); + break; + case 'rss': + $this->show_rss_groups($this->groups, $title, $link, $subtitle); + break; + case 'atom': + $selfuri = common_root_url() . + 'api/statusnet/groups/list_all.atom'; + $this->show_atom_groups( + $this->groups, + $title, + $id, + $link, + $subtitle, + $selfuri + ); + break; + case 'json': + $this->show_json_groups($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 0000000000..0cd3ed2906 --- /dev/null +++ b/actions/apigroupmembership.php @@ -0,0 +1,200 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.php'; + +/** + * List 20 newest members of the group specified by name or ID. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 TwitterApiAction +{ + var $format = null; + var $page = null; + var $count = null; + var $max_id = null; + var $since_id = null; + var $since = null; + 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->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->max_id = (int)$this->arg('max_id', 0); + $this->since_id = (int)$this->arg('since_id', 0); + $this->since = $this->arg('since'); + + $this->format = $this->arg('format'); + $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->show_twitter_xml_users($this->profiles); + break; + case 'json': + $this->show_json_users($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 0000000000..733c9ccfe6 --- /dev/null +++ b/actions/apigroupshow.php @@ -0,0 +1,148 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.php'; + +/** + * Outputs detailed information about the group specified by ID + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 TwitterApiAction +{ + var $format = null; + var $group = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + $this->format = $this->arg('format'); + $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->show_single_json_group($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/twitapigroups.php b/actions/twitapigroups.php deleted file mode 100644 index 493144e77e..0000000000 --- a/actions/twitapigroups.php +++ /dev/null @@ -1,453 +0,0 @@ -. - * - * @category Twitter - * @package StatusNet - * @author Craig Andrews - * @author Zach Copley - * @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 - * @author Zach Copley - * @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 join($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 false; - } - - if($this->auth_user->isMember($group)){ - $this->clientError(_('You are already a member of that group'), $code = 403); - return false; - } - - if (Group_block::isBlocked($group, $this->auth_user->getProfile())) { - $this->clientError(_('You have been blocked from that group by the admin.'), 403); - return false; - } - - $member = new Group_member(); - - $member->group_id = $group->id; - $member->profile_id = $this->auth_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->auth_user->nickname, $group->nickname)); - } - - 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 leave($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 false; - } - - if(! $this->auth_user->isMember($group)){ - $this->clientError(_('You are not a member of that group'), $code = 403); - return false; - } - - $member = new Group_member(); - - $member->group_id = $group->id; - $member->profile_id = $this->auth_user->id; - - if (!$member->find(true)) { - $this->serverError(_('Could not find membership record.')); - 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->auth_user->nickname, $group->nickname)); - } - - 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 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); - } - } - - function create($args, $apidata) - { - die("todo"); - } - - function update($args, $apidata) - { - die("todo"); - } - - function update_group_logo($args, $apidata) - { - die("todo"); - } - - function destroy($args, $apidata) - { - die("todo"); - } - - function tag($args, $apidata) - { - die("todo"); - } -} diff --git a/lib/router.php b/lib/router.php index dbe2be0bb4..1ea5885dac 100644 --- a/lib/router.php +++ b/lib/router.php @@ -507,27 +507,58 @@ class Router 'id' => '[a-zA-Z0-9]+', 'format' => '(xmljson|rss|atom)')); - $m->connect('api/statusnet/groups/list/:argument', - array('action' => 'api', - 'method' => 'list_groups', - 'apiaction' => 'groups')); + $m->connect('api/statusnet/groups/show.:format', + array('action' => 'ApiGroupShow', + 'format' => '(xml|json)')); - foreach (array('xml', 'json', 'rss', 'atom') as $e) { - $m->connect('api/statusnet/groups/list.' . $e, - array('action' => 'api', - 'method' => 'list_groups.' . $e, - 'apiaction' => 'groups')); - } + $m->connect('api/statusnet/groups/show/:id.:format', + array('action' => 'ApiGroupShow', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); - $m->connect('api/statusnet/groups/:method', - array('action' => 'api', - 'apiaction' => 'statuses'), - array('method' => '(list_all|)(\.(atom|rss|xml|json))?')); + $m->connect('api/statusnet/groups/join.:format', + array('action' => 'ApiGroupJoin', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); - $m->connect('api/statusnet/groups/:method', - array('action' => 'api', - 'apiaction' => 'groups')); + $m->connect('api/statusnet/groups/join/:id.:format', + array('action' => 'ApiGroupJoin', + 'format' => '(xml|json)')); + $m->connect('api/statusnet/groups/leave.:format', + array('action' => 'ApiGroupLeave', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/leave/:id.:format', + array('action' => 'ApiGroupLeave', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/is_member.:format', + array('action' => 'ApiGroupIsMember', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/list.:format', + array('action' => 'ApiGroupList', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statusnet/groups/list/:id.:format', + array('action' => 'ApiGroupList', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statusnet/groups/list_all.:format', + array('action' => 'ApiGroupListAll', + 'format' => '(xml|json|rss|atom)')); + + $m->connect('api/statusnet/groups/membership.:format', + array('action' => 'ApiGroupMembership', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/groups/membership/:id.:format', + array('action' => 'ApiGroupMembership', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); // Tags $m->connect('api/statusnet/tags/timeline/:tag.:format', array('action' => 'ApiTimelineTag', diff --git a/lib/twitterapi.php b/lib/twitterapi.php index 5cd88628bb..e5904cc858 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -829,9 +829,9 @@ class TwitterapiAction extends Action $this->elementStart('users', array('type' => 'array')); if (is_array($user)) { - foreach ($group as $g) { - $twitter_user = $this->twitter_user_array($g); - $this->show_twitter_xml_user($twitter_user,'user'); + foreach ($user as $u) { + $twitter_user = $this->twitter_user_array($u); + $this->show_twitter_xml_user($twitter_user); } } else { while ($user->fetch()) { @@ -1145,7 +1145,6 @@ class TwitterapiAction extends Action function getTargetGroup($id) { if (empty($id)) { - if (is_numeric($this->arg('id'))) { return User_group::staticGet($this->arg('id')); } else if ($this->arg('id')) { From 62059fec832014411f604d9cc669b7d3201a60d5 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 8 Oct 2009 15:45:45 -0700 Subject: [PATCH 33/49] New actions for statusnet config and version API methods --- actions/apistatusnetconfig.php | 143 ++++++++++++++++++++++++++ actions/apistatusnetversion.php | 103 +++++++++++++++++++ actions/twitapistatusnet.php | 175 -------------------------------- lib/router.php | 20 ++-- 4 files changed, 260 insertions(+), 181 deletions(-) create mode 100644 actions/apistatusnetconfig.php create mode 100644 actions/apistatusnetversion.php delete mode 100644 actions/twitapistatusnet.php diff --git a/actions/apistatusnetconfig.php b/actions/apistatusnetconfig.php new file mode 100644 index 0000000000..94bd5b4b3f --- /dev/null +++ b/actions/apistatusnetconfig.php @@ -0,0 +1,143 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.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 Zach Copley + * @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 TwitterApiAction +{ + var $format = null; + + 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); + $this->format = $this->arg('format'); + 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->init_document('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->end_document('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->init_document('json'); + $this->show_json_objects($result); + $this->end_document('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 0000000000..471297ad55 --- /dev/null +++ b/actions/apistatusnetversion.php @@ -0,0 +1,103 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.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 Zach Copley + * @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 TwitterApiAction +{ + var $format = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + $this->format = $this->arg('format'); + 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->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!'), + 404, + $this->format + ); + break; + } + } + +} + diff --git a/actions/twitapistatusnet.php b/actions/twitapistatusnet.php deleted file mode 100644 index 490f11dce2..0000000000 --- a/actions/twitapistatusnet.php +++ /dev/null @@ -1,175 +0,0 @@ -. - * - * @category Twitter - * @package StatusNet - * @author Evan Prodromou - * @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 - * @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/lib/router.php b/lib/router.php index 1ea5885dac..3c50fb25ec 100644 --- a/lib/router.php +++ b/lib/router.php @@ -486,15 +486,23 @@ class Router // statusnet - $m->connect('api/statusnet/:method', - array('action' => 'api', - 'apiaction' => 'statusnet')); + $m->connect('api/statusnet/version.:format', + array('action' => 'ApiStatusnetVersion', + 'format' => '(xml|json)')); + + $m->connect('api/statusnet/config.:format', + array('action' => 'ApiStatusnetConfig', + 'format' => '(xml|json)')); // For older methods, we provide "laconica" base action - $m->connect('api/laconica/:method', - array('action' => 'api', - 'apiaction' => 'statusnet')); + $m->connect('api/laconica/version.:format', + array('action' => 'ApiStatusnetVersion', + 'format' => '(xml|json)')); + + $m->connect('api/laconica/config.:format', + array('action' => 'ApiStatusnetConfig', + 'format' => '(xml|json)')); // Groups and tags are newer than 0.8.1 so no backward-compatibility // necessary From ada84698f2e82c1c659d872dea0c4545ef93509a Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 8 Oct 2009 15:59:00 -0700 Subject: [PATCH 34/49] New action for test/help API method --- actions/apihelptest.php | 96 +++++++++++++++++++++++++++++++++++++++++ lib/router.php | 6 +-- 2 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 actions/apihelptest.php diff --git a/actions/apihelptest.php b/actions/apihelptest.php new file mode 100644 index 0000000000..5f32165cf6 --- /dev/null +++ b/actions/apihelptest.php @@ -0,0 +1,96 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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/twitterapi.php'; + +/** + * Returns the string "ok" in the requested format with a 200 OK HTTP status code. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 TwitterApiAction +{ + var $format = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + $this->format = $this->arg('format'); + return true; + } + + /** + * Handle the request + * + * @param array $args $_REQUEST data (unused) + * + * @return void + */ + + function handle($args) + { + parent::handle($args); + + if ($this->format == 'xml') { + $this->init_document('xml'); + $this->element('ok', null, 'true'); + $this->end_document('xml'); + } elseif ($this->format == 'json') { + $this->init_document('json'); + print '"ok"'; + $this->end_document('json'); + } else { + $this->clientError( + _('API method not found!'), + 404, + $this->format + ); + } + } + +} + diff --git a/lib/router.php b/lib/router.php index 3c50fb25ec..cf5c06b26f 100644 --- a/lib/router.php +++ b/lib/router.php @@ -480,9 +480,9 @@ class Router // help - $m->connect('api/help/:method', - array('action' => 'api', - 'apiaction' => 'help')); + $m->connect('api/help/test.:format', + array('action' => 'ApiHelpTest', + 'format' => '(xml|json)')); // statusnet From 09f4d1ef236c160afe6b9874793e43b501e1120a Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 9 Oct 2009 13:35:54 -0700 Subject: [PATCH 35/49] New actions for blocks via API --- actions/apiblockcreate.php | 121 ++++++++++++++++++++++++++++++++++++ actions/apiblockdestroy.php | 120 +++++++++++++++++++++++++++++++++++ actions/twitapiblocks.php | 74 ---------------------- actions/twitapihelp.php | 57 ----------------- lib/router.php | 11 +++- 5 files changed, 249 insertions(+), 134 deletions(-) create mode 100644 actions/apiblockcreate.php create mode 100644 actions/apiblockdestroy.php delete mode 100644 actions/twitapiblocks.php delete mode 100644 actions/twitapihelp.php diff --git a/actions/apiblockcreate.php b/actions/apiblockcreate.php new file mode 100644 index 0000000000..ff303863ec --- /dev/null +++ b/actions/apiblockcreate.php @@ -0,0 +1,121 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $user = null; + var $other = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->user = $this->auth_user; + $this->other = $this->getTargetUser($this->arg('id')); + $this->format = $this->arg('format'); + + 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->init_document($this->format); + $this->show_profile($this->other, $this->format); + $this->end_document($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 0000000000..0f24be3aaf --- /dev/null +++ b/actions/apiblockdestroy.php @@ -0,0 +1,120 @@ +. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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 Zach Copley + * @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 $format = null; + var $user = null; + var $other = null; + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + if ($this->checkBasicAuthUser() == false) { + return; + } + } + + $this->user = $this->auth_user; + $this->other = $this->getTargetUser($this->arg('id')); + $this->format = $this->arg('format'); + + 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->init_document($this->format); + $this->show_profile($this->other, $this->format); + $this->end_document($this->format); + } else { + $this->serverError(_('Unblock user failed.')); + } + + } + +} + diff --git a/actions/twitapiblocks.php b/actions/twitapiblocks.php deleted file mode 100644 index ed17946aef..0000000000 --- a/actions/twitapiblocks.php +++ /dev/null @@ -1,74 +0,0 @@ -. - */ - -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/twitapihelp.php b/actions/twitapihelp.php deleted file mode 100644 index 81381620e7..0000000000 --- a/actions/twitapihelp.php +++ /dev/null @@ -1,57 +0,0 @@ -. - */ - -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/lib/router.php b/lib/router.php index cf5c06b26f..11f913f6e0 100644 --- a/lib/router.php +++ b/lib/router.php @@ -474,10 +474,15 @@ class Router // blocks - $m->connect('api/blocks/:method/:argument', - array('action' => 'api', - 'apiaction' => 'blocks')); + $m->connect('api/blocks/create/:id.:format', + array('action' => 'ApiBlockCreate', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); + $m->connect('api/blocks/destroy/:id.:format', + array('action' => 'ApiBlockDestroy', + 'id' => '[a-zA-Z0-9]+', + 'format' => '(xml|json)')); // help $m->connect('api/help/test.:format', From bb08611def2309711f91c1ab6cdab92fb7c069b2 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 9 Oct 2009 14:22:18 -0700 Subject: [PATCH 36/49] Delete action/api.php and rename lib/twitterapi.php to lib/api.php --- actions/api.php | 306 ---------------------------- actions/apifriendshipsexists.php | 2 +- actions/apigrouplistall.php | 2 +- actions/apigroupmembership.php | 2 +- actions/apigroupshow.php | 2 +- actions/apihelptest.php | 2 +- actions/apistatusesshow.php | 4 +- actions/apistatusnetconfig.php | 2 +- actions/apistatusnetversion.php | 2 +- actions/apitimelinegroup.php | 4 +- actions/apitimelinepublic.php | 4 +- actions/apitimelinetag.php | 4 +- actions/apiusershow.php | 2 +- actions/twitapinotifications.php | 40 ---- actions/twitapisearchatom.php | 6 +- actions/twitapisearchjson.php | 6 +- actions/twitapitrends.php | 6 +- lib/{twitterapi.php => api.php} | 32 ++- lib/apiauth.php | 4 +- plugins/Realtime/RealtimePlugin.php | 2 +- 20 files changed, 54 insertions(+), 380 deletions(-) delete mode 100644 actions/api.php delete mode 100644 actions/twitapinotifications.php rename lib/{twitterapi.php => api.php} (98%) diff --git a/actions/api.php b/actions/api.php deleted file mode 100644 index 1bc90de110..0000000000 --- a/actions/api.php +++ /dev/null @@ -1,306 +0,0 @@ -. - * - * @category Actions - * @package Actions - * @author Evan Prodromou - * @author Brenda Wallace - * @author Jeffery To - * @author Robin Millette - * @author Tom Adams - * @author Christopher Vollick - * @author CiaranG - * @author Craig Andrews - * @author Gina Haeussge - * @author Mike Cochrane - * @author Sarven Capadisli - * @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/home_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/apifriendshipsexists.php b/actions/apifriendshipsexists.php index 3d6e7448de..d1d5d520fc 100644 --- a/actions/apifriendshipsexists.php +++ b/actions/apifriendshipsexists.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/twitterapi.php'; +require_once INSTALLDIR.'/lib/api.php'; /** * Tests for the existence of friendship between two users. Will return true if diff --git a/actions/apigrouplistall.php b/actions/apigrouplistall.php index b1964d8005..80dcad9dcd 100644 --- a/actions/apigrouplistall.php +++ b/actions/apigrouplistall.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR . '/lib/twitterapi.php'; +require_once INSTALLDIR . '/lib/api.php'; /** * Returns of the lastest 20 groups for the site diff --git a/actions/apigroupmembership.php b/actions/apigroupmembership.php index 0cd3ed2906..872ee45eee 100644 --- a/actions/apigroupmembership.php +++ b/actions/apigroupmembership.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR . '/lib/twitterapi.php'; +require_once INSTALLDIR . '/lib/api.php'; /** * List 20 newest members of the group specified by name or ID. diff --git a/actions/apigroupshow.php b/actions/apigroupshow.php index 733c9ccfe6..a38d50afe7 100644 --- a/actions/apigroupshow.php +++ b/actions/apigroupshow.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/twitterapi.php'; +require_once INSTALLDIR.'/lib/api.php'; /** * Outputs detailed information about the group specified by ID diff --git a/actions/apihelptest.php b/actions/apihelptest.php index 5f32165cf6..2cec464627 100644 --- a/actions/apihelptest.php +++ b/actions/apihelptest.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR . '/lib/twitterapi.php'; +require_once INSTALLDIR . '/lib/api.php'; /** * Returns the string "ok" in the requested format with a 200 OK HTTP status code. diff --git a/actions/apistatusesshow.php b/actions/apistatusesshow.php index 55eea2356d..9e28fe2ab6 100644 --- a/actions/apistatusesshow.php +++ b/actions/apistatusesshow.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/twitterapi.php'; +require_once INSTALLDIR.'/lib/api.php'; /** * Returns the notice specified by id as a Twitter-style status and inline user @@ -43,7 +43,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; * @link http://status.net/ */ -class ApiStatusesShowAction extends TwitterapiAction +class ApiStatusesShowAction extends ApiAction { var $notice_id = null; diff --git a/actions/apistatusnetconfig.php b/actions/apistatusnetconfig.php index 94bd5b4b3f..6847a48fe1 100644 --- a/actions/apistatusnetconfig.php +++ b/actions/apistatusnetconfig.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR . '/lib/twitterapi.php'; +require_once INSTALLDIR . '/lib/api.php'; /** * Gives a full dump of configuration variables for this instance diff --git a/actions/apistatusnetversion.php b/actions/apistatusnetversion.php index 471297ad55..e6f35e7d29 100644 --- a/actions/apistatusnetversion.php +++ b/actions/apistatusnetversion.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR . '/lib/twitterapi.php'; +require_once INSTALLDIR . '/lib/api.php'; /** * Returns a version number for this version of StatusNet, which diff --git a/actions/apitimelinegroup.php b/actions/apitimelinegroup.php index 11f73eeedb..9d6ac6ad18 100644 --- a/actions/apitimelinegroup.php +++ b/actions/apitimelinegroup.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR . '/lib/twitterapi.php'; +require_once INSTALLDIR . '/lib/api.php'; /** * Returns the most recent notices (default 20) posted to the group specified by ID @@ -43,7 +43,7 @@ require_once INSTALLDIR . '/lib/twitterapi.php'; * @link http://status.net/ */ -class ApiTimelineGroupAction extends TwitterapiAction +class ApiTimelineGroupAction extends ApiAction { var $group = null; diff --git a/actions/apitimelinepublic.php b/actions/apitimelinepublic.php index 10bde6f37d..2638dd2926 100644 --- a/actions/apitimelinepublic.php +++ b/actions/apitimelinepublic.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/twitterapi.php'; +require_once INSTALLDIR.'/lib/api.php'; /** * Returns the most recent notices (default 20) posted by everybody @@ -43,7 +43,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; * @link http://status.net/ */ -class ApiTimelinePublicAction extends TwitterapiAction +class ApiTimelinePublicAction extends ApiAction { var $notices = null; diff --git a/actions/apitimelinetag.php b/actions/apitimelinetag.php index 2a23bb72a2..0efe8d2449 100644 --- a/actions/apitimelinetag.php +++ b/actions/apitimelinetag.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/twitterapi.php'; +require_once INSTALLDIR.'/lib/api.php'; /** * Returns the 20 most recent notices tagged by a given tag @@ -43,7 +43,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; * @link http://status.net/ */ -class ApiTimelineTagAction extends TwitterapiAction +class ApiTimelineTagAction extends ApiAction { var $notices = null; diff --git a/actions/apiusershow.php b/actions/apiusershow.php index 2e2ceab41b..afcbd3618d 100644 --- a/actions/apiusershow.php +++ b/actions/apiusershow.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/twitterapi.php'; +require_once INSTALLDIR.'/lib/api.php'; /** * Ouputs information for a user, specified by ID or screen name. diff --git a/actions/twitapinotifications.php b/actions/twitapinotifications.php deleted file mode 100644 index 0653e69ab5..0000000000 --- a/actions/twitapinotifications.php +++ /dev/null @@ -1,40 +0,0 @@ -. - */ - -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 2f587d604f..0ef9d28260 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; diff --git a/actions/twitapisearchjson.php b/actions/twitapisearchjson.php index c628ee624a..5abff6496e 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 * @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; diff --git a/actions/twitapitrends.php b/actions/twitapitrends.php index 83ab28f35d..779405e6d6 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/lib/twitterapi.php b/lib/api.php similarity index 98% rename from lib/twitterapi.php rename to lib/api.php index e5904cc858..93b4a75138 100644 --- a/lib/twitterapi.php +++ b/lib/api.php @@ -1,9 +1,12 @@ . + * + * @category API + * @package StatusNet + * @author Zach Copley + * @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')) { +if (!defined('STATUSNET')) { exit(1); } -class TwitterapiAction extends Action +/** + * Contains most of the Twitter-compatible API output functions. + * + * @category API + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class ApiAction extends Action { /** diff --git a/lib/apiauth.php b/lib/apiauth.php index f0b4b6bf7f..d7f8017eb1 100644 --- a/lib/apiauth.php +++ b/lib/apiauth.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/twitterapi.php'; +require_once INSTALLDIR.'/lib/api.php'; /** * Actions extending this class will require auth @@ -43,7 +43,7 @@ require_once INSTALLDIR.'/lib/twitterapi.php'; * @link http://status.net/ */ -class ApiAuthAction extends TwitterapiAction +class ApiAuthAction extends ApiAction { var $auth_user = null; diff --git a/plugins/Realtime/RealtimePlugin.php b/plugins/Realtime/RealtimePlugin.php index 1819279686..31e75221be 100644 --- a/plugins/Realtime/RealtimePlugin.php +++ b/plugins/Realtime/RealtimePlugin.php @@ -242,7 +242,7 @@ class RealtimePlugin extends Plugin // of refactoring from within a plugin, so I'm just abusing // the TwitterApiAction method. Don't do this unless you're me! - require_once(INSTALLDIR.'/lib/twitterapi.php'); + require_once(INSTALLDIR.'/lib/api.php'); $act = new TwitterApiAction('/dev/null'); From f746993c2bfb674d397cf095a2ab2ff7e757818b Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 9 Oct 2009 14:42:01 -0700 Subject: [PATCH 37/49] $format is used by every API action. Set it in the base class. --- actions/apiaccountratelimitstatus.php | 3 --- actions/apiaccountverifycredentials.php | 3 --- actions/apiblockcreate.php | 2 -- actions/apiblockdestroy.php | 2 -- actions/apidirectmessage.php | 3 --- actions/apidirectmessagenew.php | 3 --- actions/apifavoritecreate.php | 3 --- actions/apifavoritedestroy.php | 3 +-- actions/apifriendshipscreate.php | 3 --- actions/apifriendshipsdestroy.php | 3 --- actions/apifriendshipsexists.php | 4 ---- actions/apifriendshipsshow.php | 4 ---- actions/apigroupshow.php | 2 -- actions/apihelptest.php | 2 -- actions/apistatusnetconfig.php | 3 --- actions/apistatusnetversion.php | 3 --- actions/apiusershow.php | 4 ---- lib/api.php | 2 ++ 18 files changed, 3 insertions(+), 49 deletions(-) diff --git a/actions/apiaccountratelimitstatus.php b/actions/apiaccountratelimitstatus.php index 3c6c3e714d..9eba5c55db 100644 --- a/actions/apiaccountratelimitstatus.php +++ b/actions/apiaccountratelimitstatus.php @@ -46,8 +46,6 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; class ApiAccountRateLimitStatusAction extends ApiBareAuthAction { - var $format = null; - /** * Take arguments for running * @@ -67,7 +65,6 @@ class ApiAccountRateLimitStatusAction extends ApiBareAuthAction } } - $this->format = $this->arg('format'); return true; } diff --git a/actions/apiaccountverifycredentials.php b/actions/apiaccountverifycredentials.php index b9c9bf0f72..0d4928f6ce 100644 --- a/actions/apiaccountverifycredentials.php +++ b/actions/apiaccountverifycredentials.php @@ -47,8 +47,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiAccountVerifyCredentialsAction extends ApiAuthAction { - var $format = null; - /** * Take arguments for running * @@ -68,7 +66,6 @@ class ApiAccountVerifyCredentialsAction extends ApiAuthAction } } - $this->format = $this->arg('format'); return true; } diff --git a/actions/apiblockcreate.php b/actions/apiblockcreate.php index ff303863ec..6421712713 100644 --- a/actions/apiblockcreate.php +++ b/actions/apiblockcreate.php @@ -47,7 +47,6 @@ require_once INSTALLDIR . '/lib/apiauth.php'; class ApiBlockCreateAction extends ApiAuthAction { - var $format = null; var $user = null; var $other = null; @@ -72,7 +71,6 @@ class ApiBlockCreateAction extends ApiAuthAction $this->user = $this->auth_user; $this->other = $this->getTargetUser($this->arg('id')); - $this->format = $this->arg('format'); return true; } diff --git a/actions/apiblockdestroy.php b/actions/apiblockdestroy.php index 0f24be3aaf..109e66ac41 100644 --- a/actions/apiblockdestroy.php +++ b/actions/apiblockdestroy.php @@ -46,7 +46,6 @@ require_once INSTALLDIR . '/lib/apiauth.php'; class ApiBlockDestroyAction extends ApiAuthAction { - var $format = null; var $user = null; var $other = null; @@ -71,7 +70,6 @@ class ApiBlockDestroyAction extends ApiAuthAction $this->user = $this->auth_user; $this->other = $this->getTargetUser($this->arg('id')); - $this->format = $this->arg('format'); return true; } diff --git a/actions/apidirectmessage.php b/actions/apidirectmessage.php index 87ae44d7a5..fa68833117 100644 --- a/actions/apidirectmessage.php +++ b/actions/apidirectmessage.php @@ -45,7 +45,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiDirectMessageAction extends ApiAuthAction { - var $format = null; var $messages = null; var $page = null; var $count = null; @@ -122,8 +121,6 @@ class ApiDirectMessageAction extends ApiAuthAction $this->id = "tag:$taguribase:DirectMessages:" . $this->user->id; } - $this->format = $this->arg('format'); - $this->messages = $this->getMessages(); return true; diff --git a/actions/apidirectmessagenew.php b/actions/apidirectmessagenew.php index d836409ae0..b531d7c5c7 100644 --- a/actions/apidirectmessagenew.php +++ b/actions/apidirectmessagenew.php @@ -46,7 +46,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiDirectMessageNewAction extends ApiAuthAction { - var $format = null; var $source = null; var $user = null; var $other = null; @@ -97,8 +96,6 @@ class ApiDirectMessageNewAction extends ApiAuthAction $this->other = $this->getTargetUser($user_param); } - $this->format = $this->arg('format'); - return true; } diff --git a/actions/apifavoritecreate.php b/actions/apifavoritecreate.php index e45603c6a2..6ee6960ba5 100644 --- a/actions/apifavoritecreate.php +++ b/actions/apifavoritecreate.php @@ -46,8 +46,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiFavoriteCreateAction extends ApiAuthAction { - - var $format = null; var $user = null; var $notice = null; @@ -70,7 +68,6 @@ class ApiFavoriteCreateAction extends ApiAuthAction } } - $this->format = $this->arg('format'); $this->user = $this->auth_user; $this->notice = Notice::staticGet($this->arg('id')); diff --git a/actions/apifavoritedestroy.php b/actions/apifavoritedestroy.php index a70d5c79b1..36946fbfbe 100644 --- a/actions/apifavoritedestroy.php +++ b/actions/apifavoritedestroy.php @@ -47,9 +47,9 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiFavoriteDestroyAction extends ApiAuthAction { - var $format = null; var $user = null; var $notice = null; + /** * Take arguments for running * @@ -69,7 +69,6 @@ class ApiFavoriteDestroyAction extends ApiAuthAction } } - $this->format = $this->arg('format'); $this->user = $this->auth_user; $this->notice = Notice::staticGet($this->arg('id')); diff --git a/actions/apifriendshipscreate.php b/actions/apifriendshipscreate.php index 969fc12820..27bdbe0623 100644 --- a/actions/apifriendshipscreate.php +++ b/actions/apifriendshipscreate.php @@ -47,8 +47,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiFriendshipsCreateAction extends ApiAuthAction { - - var $format = null; var $user = null; var $other = null; @@ -71,7 +69,6 @@ class ApiFriendshipsCreateAction extends ApiAuthAction } } - $this->format = $this->arg('format'); $this->user = $this->auth_user; $this->other = $this->getTargetUser($id); diff --git a/actions/apifriendshipsdestroy.php b/actions/apifriendshipsdestroy.php index ef864c4db8..3ad12156dd 100644 --- a/actions/apifriendshipsdestroy.php +++ b/actions/apifriendshipsdestroy.php @@ -47,8 +47,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiFriendshipsDestroyAction extends ApiAuthAction { - - var $format = null; var $user = null; var $other = null; @@ -71,7 +69,6 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction } } - $this->format = $this->arg('format'); $this->user = $this->auth_user; $this->other = $this->getTargetUser($id); diff --git a/actions/apifriendshipsexists.php b/actions/apifriendshipsexists.php index d1d5d520fc..1ebfc9e8fd 100644 --- a/actions/apifriendshipsexists.php +++ b/actions/apifriendshipsexists.php @@ -46,8 +46,6 @@ require_once INSTALLDIR.'/lib/api.php'; class ApiFriendshipsExistsAction extends TwitterApiAction { - - var $format = null; var $user_a = null; var $user_b = null; @@ -64,8 +62,6 @@ class ApiFriendshipsExistsAction extends TwitterApiAction { parent::prepare($args); - $this->format = $this->arg('format'); - $user_a_id = $this->trimmed('user_a'); $user_b_id = $this->trimmed('user_b'); diff --git a/actions/apifriendshipsshow.php b/actions/apifriendshipsshow.php index d35825a433..2f975b121b 100644 --- a/actions/apifriendshipsshow.php +++ b/actions/apifriendshipsshow.php @@ -45,8 +45,6 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; class ApiFriendshipsShowAction extends ApiBareAuthAction { - - var $format = null; var $user = null; var $source = null; var $target = null; @@ -70,8 +68,6 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction } } - $this->format = $this->arg('format'); - $source_id = (int)$this->trimmed('source_id'); $source_screen_name = $this->trimmed('source_screen_name'); $target_id = (int)$this->trimmed('target_id'); diff --git a/actions/apigroupshow.php b/actions/apigroupshow.php index a38d50afe7..cdaf707aa9 100644 --- a/actions/apigroupshow.php +++ b/actions/apigroupshow.php @@ -45,7 +45,6 @@ require_once INSTALLDIR.'/lib/api.php'; class ApiGroupShowAction extends TwitterApiAction { - var $format = null; var $group = null; /** @@ -61,7 +60,6 @@ class ApiGroupShowAction extends TwitterApiAction { parent::prepare($args); - $this->format = $this->arg('format'); $this->group = $this->getTargetGroup($this->arg('id')); return true; diff --git a/actions/apihelptest.php b/actions/apihelptest.php index 2cec464627..ac1bb1a5b3 100644 --- a/actions/apihelptest.php +++ b/actions/apihelptest.php @@ -45,7 +45,6 @@ require_once INSTALLDIR . '/lib/api.php'; class ApiHelpTestAction extends TwitterApiAction { - var $format = null; /** * Take arguments for running @@ -59,7 +58,6 @@ class ApiHelpTestAction extends TwitterApiAction function prepare($args) { parent::prepare($args); - $this->format = $this->arg('format'); return true; } diff --git a/actions/apistatusnetconfig.php b/actions/apistatusnetconfig.php index 6847a48fe1..6fb65331f4 100644 --- a/actions/apistatusnetconfig.php +++ b/actions/apistatusnetconfig.php @@ -49,8 +49,6 @@ require_once INSTALLDIR . '/lib/api.php'; class ApiStatusnetConfigAction extends TwitterApiAction { - var $format = null; - var $keys = array( 'site' => array('name', 'server', 'theme', 'path', 'fancy', 'language', 'email', 'broughtby', 'broughtbyurl', 'closed', @@ -73,7 +71,6 @@ class ApiStatusnetConfigAction extends TwitterApiAction function prepare($args) { parent::prepare($args); - $this->format = $this->arg('format'); return true; } diff --git a/actions/apistatusnetversion.php b/actions/apistatusnetversion.php index e6f35e7d29..2cd99edb7a 100644 --- a/actions/apistatusnetversion.php +++ b/actions/apistatusnetversion.php @@ -48,8 +48,6 @@ require_once INSTALLDIR . '/lib/api.php'; class ApiStatusnetVersionAction extends TwitterApiAction { - var $format = null; - /** * Take arguments for running * @@ -62,7 +60,6 @@ class ApiStatusnetVersionAction extends TwitterApiAction function prepare($args) { parent::prepare($args); - $this->format = $this->arg('format'); return true; } diff --git a/actions/apiusershow.php b/actions/apiusershow.php index afcbd3618d..1cd0cdfd5f 100644 --- a/actions/apiusershow.php +++ b/actions/apiusershow.php @@ -46,8 +46,6 @@ require_once INSTALLDIR.'/lib/api.php'; class ApiUserShowAction extends TwitterApiAction { - - var $format = null; var $user = null; /** @@ -63,8 +61,6 @@ class ApiUserShowAction extends TwitterApiAction { parent::prepare($args); - $this->format = $this->arg('format'); - $email = $this->arg('email'); // XXX: email field deprecated in Twitter's API diff --git a/lib/api.php b/lib/api.php index 93b4a75138..fb51d5260e 100644 --- a/lib/api.php +++ b/lib/api.php @@ -43,6 +43,7 @@ if (!defined('STATUSNET')) { class ApiAction extends Action { + var $format = null; /** * Initialization. @@ -55,6 +56,7 @@ class ApiAction extends Action function prepare($args) { parent::prepare($args); + $this->format = $this->arg('format'); return true; } From 743c844084bae75db02570d76694f4e9b79a9aa9 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 9 Oct 2009 16:57:22 -0700 Subject: [PATCH 38/49] Move all basic auth output and processing to base classes --- actions/apiaccountratelimitstatus.php | 21 --------------------- actions/apiaccountverifycredentials.php | 21 --------------------- actions/apiblockcreate.php | 6 ------ actions/apiblockdestroy.php | 6 ------ actions/apidirectmessage.php | 6 ------ actions/apidirectmessagenew.php | 6 ------ actions/apifavoritecreate.php | 6 ------ actions/apifavoritedestroy.php | 6 ------ actions/apifriendshipscreate.php | 6 ------ actions/apifriendshipsdestroy.php | 6 ------ actions/apifriendshipsshow.php | 6 ------ actions/apigroupismember.php | 6 ------ actions/apigroupjoin.php | 6 ------ actions/apigroupleave.php | 6 ------ actions/apigrouplist.php | 6 ------ actions/apistatusesdestroy.php | 6 ------ actions/apistatusesupdate.php | 6 ------ actions/apisubscriptions.php | 6 ------ actions/apitimelinefavorites.php | 6 ------ actions/apitimelinefriends.php | 6 ------ actions/apitimelinementions.php | 6 ------ actions/apitimelineuser.php | 6 ------ lib/apiauth.php | 24 ++++++++++++++++++++++-- lib/apibareauth.php | 16 ++++++++++++++++ 24 files changed, 38 insertions(+), 164 deletions(-) diff --git a/actions/apiaccountratelimitstatus.php b/actions/apiaccountratelimitstatus.php index 9eba5c55db..b823e1cd2b 100644 --- a/actions/apiaccountratelimitstatus.php +++ b/actions/apiaccountratelimitstatus.php @@ -46,27 +46,6 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; class ApiAccountRateLimitStatusAction extends ApiBareAuthAction { - /** - * Take arguments for running - * - * @param array $args $_REQUEST args - * - * @return boolean success flag - * - */ - - function prepare($args) - { - parent::prepare($args); - - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return false; - } - } - - return true; - } /** * Handle the request diff --git a/actions/apiaccountverifycredentials.php b/actions/apiaccountverifycredentials.php index 0d4928f6ce..104b9867fd 100644 --- a/actions/apiaccountverifycredentials.php +++ b/actions/apiaccountverifycredentials.php @@ -47,27 +47,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiAccountVerifyCredentialsAction extends ApiAuthAction { - /** - * Take arguments for running - * - * @param array $args $_REQUEST args - * - * @return boolean success flag - * - */ - - function prepare($args) - { - parent::prepare($args); - - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return false; - } - } - - return true; - } /** * Handle the request diff --git a/actions/apiblockcreate.php b/actions/apiblockcreate.php index 6421712713..6dd28dd5ef 100644 --- a/actions/apiblockcreate.php +++ b/actions/apiblockcreate.php @@ -63,12 +63,6 @@ class ApiBlockCreateAction extends ApiAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->auth_user; $this->other = $this->getTargetUser($this->arg('id')); diff --git a/actions/apiblockdestroy.php b/actions/apiblockdestroy.php index 109e66ac41..a869dfe466 100644 --- a/actions/apiblockdestroy.php +++ b/actions/apiblockdestroy.php @@ -62,12 +62,6 @@ class ApiBlockDestroyAction extends ApiAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->auth_user; $this->other = $this->getTargetUser($this->arg('id')); diff --git a/actions/apidirectmessage.php b/actions/apidirectmessage.php index fa68833117..cede4c0721 100644 --- a/actions/apidirectmessage.php +++ b/actions/apidirectmessage.php @@ -70,12 +70,6 @@ class ApiDirectMessageAction extends ApiAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->auth_user; if (empty($this->user)) { diff --git a/actions/apidirectmessagenew.php b/actions/apidirectmessagenew.php index b531d7c5c7..6984c8d103 100644 --- a/actions/apidirectmessagenew.php +++ b/actions/apidirectmessagenew.php @@ -64,12 +64,6 @@ class ApiDirectMessageNewAction extends ApiAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->auth_user; if (empty($this->user)) { diff --git a/actions/apifavoritecreate.php b/actions/apifavoritecreate.php index 6ee6960ba5..db001561ec 100644 --- a/actions/apifavoritecreate.php +++ b/actions/apifavoritecreate.php @@ -62,12 +62,6 @@ class ApiFavoriteCreateAction extends ApiAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->auth_user; $this->notice = Notice::staticGet($this->arg('id')); diff --git a/actions/apifavoritedestroy.php b/actions/apifavoritedestroy.php index 36946fbfbe..3640459f99 100644 --- a/actions/apifavoritedestroy.php +++ b/actions/apifavoritedestroy.php @@ -63,12 +63,6 @@ class ApiFavoriteDestroyAction extends ApiAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->auth_user; $this->notice = Notice::staticGet($this->arg('id')); diff --git a/actions/apifriendshipscreate.php b/actions/apifriendshipscreate.php index 27bdbe0623..85eaf3a296 100644 --- a/actions/apifriendshipscreate.php +++ b/actions/apifriendshipscreate.php @@ -63,12 +63,6 @@ class ApiFriendshipsCreateAction extends ApiAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->auth_user; $this->other = $this->getTargetUser($id); diff --git a/actions/apifriendshipsdestroy.php b/actions/apifriendshipsdestroy.php index 3ad12156dd..2743780519 100644 --- a/actions/apifriendshipsdestroy.php +++ b/actions/apifriendshipsdestroy.php @@ -63,12 +63,6 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->auth_user; $this->other = $this->getTargetUser($id); diff --git a/actions/apifriendshipsshow.php b/actions/apifriendshipsshow.php index 2f975b121b..0ae6a7b82b 100644 --- a/actions/apifriendshipsshow.php +++ b/actions/apifriendshipsshow.php @@ -62,12 +62,6 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $source_id = (int)$this->trimmed('source_id'); $source_screen_name = $this->trimmed('source_screen_name'); $target_id = (int)$this->trimmed('target_id'); diff --git a/actions/apigroupismember.php b/actions/apigroupismember.php index facc58174e..02079b6ffe 100644 --- a/actions/apigroupismember.php +++ b/actions/apigroupismember.php @@ -62,12 +62,6 @@ class ApiGroupIsMemberAction extends ApiBareAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->getTargetUser(null); $this->group = $this->getTargetGroup(null); $this->format = $this->arg('format'); diff --git a/actions/apigroupjoin.php b/actions/apigroupjoin.php index c00d594631..7ab1b72723 100644 --- a/actions/apigroupjoin.php +++ b/actions/apigroupjoin.php @@ -62,12 +62,6 @@ class ApiGroupJoinAction extends ApiAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->auth_user; $this->group = $this->getTargetGroup($this->arg('id')); diff --git a/actions/apigroupleave.php b/actions/apigroupleave.php index 568b04b7cf..86b56f5af0 100644 --- a/actions/apigroupleave.php +++ b/actions/apigroupleave.php @@ -62,12 +62,6 @@ class ApiGroupLeaveAction extends ApiAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->auth_user; $this->group = $this->getTargetGroup($this->arg('id')); diff --git a/actions/apigrouplist.php b/actions/apigrouplist.php index 84b7fc1c8c..69c347de12 100644 --- a/actions/apigrouplist.php +++ b/actions/apigrouplist.php @@ -67,12 +67,6 @@ class ApiGroupListAction extends ApiBareAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->page = (int)$this->arg('page', 1); $this->count = (int)$this->arg('count', 20); $this->max_id = (int)$this->arg('max_id', 0); diff --git a/actions/apistatusesdestroy.php b/actions/apistatusesdestroy.php index ae0f4c4532..16a7cc376e 100644 --- a/actions/apistatusesdestroy.php +++ b/actions/apistatusesdestroy.php @@ -63,12 +63,6 @@ class ApiStatusesDestroyAction extends ApiAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return false; - } - } - $this->user = $this->auth_user; $this->notice_id = (int)$this->trimmed('id'); diff --git a/actions/apistatusesupdate.php b/actions/apistatusesupdate.php index fb12785593..ab33d8a3e9 100644 --- a/actions/apistatusesupdate.php +++ b/actions/apistatusesupdate.php @@ -67,12 +67,6 @@ class ApiStatusesUpdateAction extends ApiAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return false; - } - } - $this->user = $this->auth_user; if (empty($this->user)) { diff --git a/actions/apisubscriptions.php b/actions/apisubscriptions.php index 78dcd722dd..bdaa0ea39a 100644 --- a/actions/apisubscriptions.php +++ b/actions/apisubscriptions.php @@ -84,12 +84,6 @@ class ApiSubscriptionsAction extends ApiBareAuthAction $this->count = isset($this->ids_only) ? 5000 : (int)$this->arg('count', 100); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return false; - } - } - $this->user = $this->getTargetUser($this->arg('id')); if (empty($this->user)) { diff --git a/actions/apitimelinefavorites.php b/actions/apitimelinefavorites.php index 9ccee5cfac..35a996c9cb 100644 --- a/actions/apitimelinefavorites.php +++ b/actions/apitimelinefavorites.php @@ -69,12 +69,6 @@ class ApiTimelineFavoritesAction extends ApiBareAuthAction { parent::prepare($args); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->page = (int)$this->arg('page', 1); $this->count = (int)$this->arg('count', 20); $this->max_id = (int)$this->arg('max_id', 0); diff --git a/actions/apitimelinefriends.php b/actions/apitimelinefriends.php index 65bbb5a74a..92a8852936 100644 --- a/actions/apitimelinefriends.php +++ b/actions/apitimelinefriends.php @@ -75,12 +75,6 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction $this->since = $this->arg('since'); $this->format = $this->arg('format'); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->getTargetUser($this->arg('id')); if (empty($this->user)) { diff --git a/actions/apitimelinementions.php b/actions/apitimelinementions.php index 93c6da3073..ecead98cce 100644 --- a/actions/apitimelinementions.php +++ b/actions/apitimelinementions.php @@ -68,12 +68,6 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction $this->since_id = (int)$this->arg('since_id', 0); $this->since = $this->arg('since'); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->getTargetUser($this->arg('id')); if (empty($this->user)) { diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php index c4d02bc622..d50648d7c9 100644 --- a/actions/apitimelineuser.php +++ b/actions/apitimelineuser.php @@ -70,12 +70,6 @@ class ApiTimelineUserAction extends ApiBareAuthAction $this->since_id = (int)$this->arg('since_id', 0); $this->since = $this->arg('since'); - if ($this->requiresAuth()) { - if ($this->checkBasicAuthUser() == false) { - return; - } - } - $this->user = $this->getTargetUser($this->arg('id')); if (empty($this->user)) { diff --git a/lib/apiauth.php b/lib/apiauth.php index d7f8017eb1..9fc0e57124 100644 --- a/lib/apiauth.php +++ b/lib/apiauth.php @@ -48,6 +48,26 @@ class ApiAuthAction extends ApiAction var $auth_user = null; + /** + * Take arguments for running, and output basic auth header if needed + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + + if ($this->requiresAuth()) { + $this->checkBasicAuthUser(); + } + + return true; + } + /** * Does this API resource require authentication? * @@ -76,7 +96,7 @@ class ApiAuthAction extends ApiAction // show error if the user clicks 'cancel' $this->showBasicAuthError(); - return false; + exit; } else { $nickname = $this->auth_user; @@ -94,7 +114,7 @@ class ApiAuthAction extends ApiAction "$nickname, proxy = $proxy, ip = $ip." ); $this->showBasicAuthError(); - return false; + exit; } } return true; diff --git a/lib/apibareauth.php b/lib/apibareauth.php index a99d450ecc..0ae477f468 100644 --- a/lib/apibareauth.php +++ b/lib/apibareauth.php @@ -48,6 +48,22 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiBareAuthAction extends ApiAuthAction { + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + */ + + function prepare($args) + { + parent::prepare($args); + return true; + } + /** * Does this API resource require authentication? * From 931e19073d522a41a54b5e9a77b213a10da95476 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 9 Oct 2009 17:01:37 -0700 Subject: [PATCH 39/49] Remove dead code --- lib/api.php | 63 ----------------------------------------------------- 1 file changed, 63 deletions(-) diff --git a/lib/api.php b/lib/api.php index fb51d5260e..3afb20612d 100644 --- a/lib/api.php +++ b/lib/api.php @@ -308,23 +308,6 @@ class ApiAction extends Action $entry['enclosures'] = $enclosures; } -/* - // Enclosure - $attachments = $notice->attachments(); - if($attachments){ - $entry['enclosures']=array(); - foreach($attachments as $attachment){ - if ($attachment->isEnclosure()) { - $enclosure=array(); - $enclosure['url']=$attachment->url; - $enclosure['mimetype']=$attachment->mimetype; - $enclosure['size']=$attachment->size; - $entry['enclosures'][]=$enclosure; - } - } - } -*/ - // Tags/Categories $tag = new Notice_tag(); $tag->notice_id = $notice->id; @@ -1100,38 +1083,6 @@ class ApiAction extends Action return; } - function get_user($id, $apidata=null) - { - if (empty($id)) { - - // Twitter supports these other ways of passing the user ID - if (is_numeric($this->arg('id'))) { - return User::staticGet($this->arg('id')); - } else if ($this->arg('id')) { - $nickname = common_canonical_nickname($this->arg('id')); - return User::staticGet('nickname', $nickname); - } else if ($this->arg('user_id')) { - // This is to ensure that a non-numeric user_id still - // overrides screen_name even if it doesn't get used - if (is_numeric($this->arg('user_id'))) { - return User::staticGet('id', $this->arg('user_id')); - } - } else if ($this->arg('screen_name')) { - $nickname = common_canonical_nickname($this->arg('screen_name')); - return User::staticGet('nickname', $nickname); - } else { - // Fall back to trying the currently authenticated user - return $apidata['user']; - } - - } else if (is_numeric($id)) { - return User::staticGet($id); - } else { - $nickname = common_canonical_nickname($id); - return User::staticGet('nickname', $nickname); - } - } - function getTargetUser($id) { if (empty($id)) { @@ -1191,20 +1142,6 @@ class ApiAction extends Action } } - function get_profile($id) - { - if (is_numeric($id)) { - return Profile::staticGet($id); - } else { - $user = User::staticGet('nickname', $id); - if ($user) { - return $user->getProfile(); - } else { - return null; - } - } - } - function source_link($source) { $source_name = _($source); From 559918826a714c1ee2ecdc49dcfc2b67451a9864 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 9 Oct 2009 17:11:40 -0700 Subject: [PATCH 40/49] Remove more redundant $formats --- actions/apigroupismember.php | 2 -- actions/apigroupjoin.php | 3 --- actions/apigroupleave.php | 3 --- actions/apigrouplist.php | 2 -- actions/apigrouplistall.php | 2 -- actions/apigroupmembership.php | 2 -- actions/apistatusesdestroy.php | 2 -- actions/apistatusesshow.php | 2 -- actions/apistatusesupdate.php | 3 --- actions/apisubscriptions.php | 2 -- actions/apitimelinefavorites.php | 2 -- actions/apitimelinefriends.php | 2 -- actions/apitimelinegroup.php | 1 - actions/apitimelinementions.php | 4 ++-- actions/apitimelinepublic.php | 2 +- actions/apitimelinetag.php | 1 - actions/apitimelineuser.php | 4 ++-- lib/apiauth.php | 4 ++-- 18 files changed, 7 insertions(+), 36 deletions(-) diff --git a/actions/apigroupismember.php b/actions/apigroupismember.php index 02079b6ffe..359b7ca4fa 100644 --- a/actions/apigroupismember.php +++ b/actions/apigroupismember.php @@ -45,7 +45,6 @@ require_once INSTALLDIR . '/lib/apibareauth.php'; class ApiGroupIsMemberAction extends ApiBareAuthAction { - var $format = null; var $user = null; var $group = null; @@ -64,7 +63,6 @@ class ApiGroupIsMemberAction extends ApiBareAuthAction $this->user = $this->getTargetUser(null); $this->group = $this->getTargetGroup(null); - $this->format = $this->arg('format'); return true; } diff --git a/actions/apigroupjoin.php b/actions/apigroupjoin.php index 7ab1b72723..e51842bcb6 100644 --- a/actions/apigroupjoin.php +++ b/actions/apigroupjoin.php @@ -45,7 +45,6 @@ require_once INSTALLDIR . '/lib/apiauth.php'; class ApiGroupJoinAction extends ApiAuthAction { - var $format = null; var $user = null; var $group = null; @@ -65,8 +64,6 @@ class ApiGroupJoinAction extends ApiAuthAction $this->user = $this->auth_user; $this->group = $this->getTargetGroup($this->arg('id')); - $this->format = $this->arg('format'); - return true; } diff --git a/actions/apigroupleave.php b/actions/apigroupleave.php index 86b56f5af0..332bd7b7b2 100644 --- a/actions/apigroupleave.php +++ b/actions/apigroupleave.php @@ -45,7 +45,6 @@ require_once INSTALLDIR . '/lib/apiauth.php'; class ApiGroupLeaveAction extends ApiAuthAction { - var $format = null; var $user = null; var $group = null; @@ -65,8 +64,6 @@ class ApiGroupLeaveAction extends ApiAuthAction $this->user = $this->auth_user; $this->group = $this->getTargetGroup($this->arg('id')); - $this->format = $this->arg('format'); - return true; } diff --git a/actions/apigrouplist.php b/actions/apigrouplist.php index 69c347de12..00ceeed760 100644 --- a/actions/apigrouplist.php +++ b/actions/apigrouplist.php @@ -45,7 +45,6 @@ require_once INSTALLDIR . '/lib/apibareauth.php'; class ApiGroupListAction extends ApiBareAuthAction { - var $format = null; var $user = null; var $page = null; var $count = null; @@ -74,7 +73,6 @@ class ApiGroupListAction extends ApiBareAuthAction $this->since = $this->arg('since'); $this->user = $this->getTargetUser($id); - $this->format = $this->arg('format'); $this->groups = $this->getGroups(); return true; diff --git a/actions/apigrouplistall.php b/actions/apigrouplistall.php index 80dcad9dcd..a0f04ed760 100644 --- a/actions/apigrouplistall.php +++ b/actions/apigrouplistall.php @@ -45,7 +45,6 @@ require_once INSTALLDIR . '/lib/api.php'; class ApiGroupListAllAction extends TwitterApiAction { - var $format = null; var $page = null; var $count = null; var $max_id = null; @@ -73,7 +72,6 @@ class ApiGroupListAllAction extends TwitterApiAction $this->since = $this->arg('since'); $this->user = $this->getTargetUser($id); - $this->format = $this->arg('format'); $this->groups = $this->getGroups(); return true; diff --git a/actions/apigroupmembership.php b/actions/apigroupmembership.php index 872ee45eee..da510ff26b 100644 --- a/actions/apigroupmembership.php +++ b/actions/apigroupmembership.php @@ -45,7 +45,6 @@ require_once INSTALLDIR . '/lib/api.php'; class ApiGroupMembershipAction extends TwitterApiAction { - var $format = null; var $page = null; var $count = null; var $max_id = null; @@ -73,7 +72,6 @@ class ApiGroupMembershipAction extends TwitterApiAction $this->since_id = (int)$this->arg('since_id', 0); $this->since = $this->arg('since'); - $this->format = $this->arg('format'); $this->group = $this->getTargetGroup($this->arg('id')); $this->profiles = $this->getProfiles(); diff --git a/actions/apistatusesdestroy.php b/actions/apistatusesdestroy.php index 16a7cc376e..7680f96dcf 100644 --- a/actions/apistatusesdestroy.php +++ b/actions/apistatusesdestroy.php @@ -48,7 +48,6 @@ class ApiStatusesDestroyAction extends ApiAuthAction var $user = null; var $status = null; - var $format = null; /** * Take arguments for running @@ -70,7 +69,6 @@ class ApiStatusesDestroyAction extends ApiAuthAction $this->notice_id = (int)$this->arg('id'); } - $this->format = $this->arg('format'); $this->notice = Notice::staticGet((int)$this->notice_id); return true; diff --git a/actions/apistatusesshow.php b/actions/apistatusesshow.php index 9e28fe2ab6..0096cfe6b9 100644 --- a/actions/apistatusesshow.php +++ b/actions/apistatusesshow.php @@ -48,7 +48,6 @@ class ApiStatusesShowAction extends ApiAction var $notice_id = null; var $notice = null; - var $format = null; /** * Take arguments for running @@ -74,7 +73,6 @@ class ApiStatusesShowAction extends ApiAction $this->notice_id = (int)$this->arg('id'); } - $this->format = $this->arg('format'); $this->notice = Notice::staticGet((int)$this->notice_id); return true; diff --git a/actions/apistatusesupdate.php b/actions/apistatusesupdate.php index ab33d8a3e9..7d6a574ef0 100644 --- a/actions/apistatusesupdate.php +++ b/actions/apistatusesupdate.php @@ -50,7 +50,6 @@ class ApiStatusesUpdateAction extends ApiAuthAction var $source = null; var $status = null; var $in_reply_to_status_id = null; - var $format = null; static $reserved_sources = array('web', 'omb', 'mail', 'xmpp', 'api'); @@ -92,8 +91,6 @@ class ApiStatusesUpdateAction extends ApiAuthAction $this->source = 'api'; } - $this->format = $this->arg('format'); - $this->in_reply_to_status_id = intval($this->trimmed('in_reply_to_status_id')); diff --git a/actions/apisubscriptions.php b/actions/apisubscriptions.php index bdaa0ea39a..9dbddbd9bd 100644 --- a/actions/apisubscriptions.php +++ b/actions/apisubscriptions.php @@ -52,7 +52,6 @@ class ApiSubscriptionsAction extends ApiBareAuthAction var $count = null; var $user = null; var $profiles = null; - var $format = null; var $tag = null; var $lite = null; var $ids_only = null; @@ -72,7 +71,6 @@ class ApiSubscriptionsAction extends ApiBareAuthAction $this->page = (int)$this->arg('page', 1); $this->tag = $this->arg('tag'); - $this->format = $this->arg('format'); // Note: Twitter no longer supports 'lite' $this->lite = $this->arg('lite'); diff --git a/actions/apitimelinefavorites.php b/actions/apitimelinefavorites.php index 35a996c9cb..231f2ae49c 100644 --- a/actions/apitimelinefavorites.php +++ b/actions/apitimelinefavorites.php @@ -49,7 +49,6 @@ class ApiTimelineFavoritesAction extends ApiBareAuthAction var $user = null; var $notices = null; - var $format = null; var $page = null; var $count = null; var $max_id = null; @@ -74,7 +73,6 @@ class ApiTimelineFavoritesAction extends ApiBareAuthAction $this->max_id = (int)$this->arg('max_id', 0); $this->since_id = (int)$this->arg('since_id', 0); $this->since = $this->arg('since'); - $this->format = $this->arg('format'); $this->user = $this->getTargetUser($this->arg('id')); diff --git a/actions/apitimelinefriends.php b/actions/apitimelinefriends.php index 92a8852936..02e3525695 100644 --- a/actions/apitimelinefriends.php +++ b/actions/apitimelinefriends.php @@ -53,7 +53,6 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction var $max_id = null; var $since_id = null; var $since = null; - var $format = null; /** * Take arguments for running @@ -73,7 +72,6 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction $this->max_id = (int)$this->arg('max_id', 0); $this->since_id = (int)$this->arg('since_id', 0); $this->since = $this->arg('since'); - $this->format = $this->arg('format'); $this->user = $this->getTargetUser($this->arg('id')); diff --git a/actions/apitimelinegroup.php b/actions/apitimelinegroup.php index 9d6ac6ad18..abe7f0c5d8 100644 --- a/actions/apitimelinegroup.php +++ b/actions/apitimelinegroup.php @@ -70,7 +70,6 @@ class ApiTimelineGroupAction extends ApiAction $this->group = $this->getTargetGroup($this->arg('id')); - $this->format = $this->arg('format'); $this->notices = $this->getNotices(); return true; diff --git a/actions/apitimelinementions.php b/actions/apitimelinementions.php index ecead98cce..7549b4722d 100644 --- a/actions/apitimelinementions.php +++ b/actions/apitimelinementions.php @@ -71,7 +71,7 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction $this->user = $this->getTargetUser($this->arg('id')); if (empty($this->user)) { - $this->clientError(_('No such user!'), 404, $this->arg('format')); + $this->clientError(_('No such user!'), 404, $this->format); return; } @@ -122,7 +122,7 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction $sitename, $this->user->nickname, $profile->getBestName() ); - switch($this->arg('format')) { + switch($this->format) { case 'xml': $this->show_xml_timeline($this->notices); break; diff --git a/actions/apitimelinepublic.php b/actions/apitimelinepublic.php index 2638dd2926..a635ddc91e 100644 --- a/actions/apitimelinepublic.php +++ b/actions/apitimelinepublic.php @@ -103,7 +103,7 @@ class ApiTimelinePublicAction extends ApiAction $link = common_root_url(); $subtitle = sprintf(_("%s updates from everyone!"), $sitename); - switch($this->arg('format')) { + switch($this->format) { case 'xml': $this->show_xml_timeline($this->notices); break; diff --git a/actions/apitimelinetag.php b/actions/apitimelinetag.php index 0efe8d2449..8211b01226 100644 --- a/actions/apitimelinetag.php +++ b/actions/apitimelinetag.php @@ -64,7 +64,6 @@ class ApiTimelineTagAction extends ApiAction $this->page = (int)$this->arg('page', 1); $this->count = (int)$this->arg('count', 20); $this->tag = $this->arg('tag'); - $this->format = $this->arg('format'); $this->notices = $this->getNotices(); diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php index d50648d7c9..81e23116b7 100644 --- a/actions/apitimelineuser.php +++ b/actions/apitimelineuser.php @@ -73,7 +73,7 @@ class ApiTimelineUserAction extends ApiBareAuthAction $this->user = $this->getTargetUser($this->arg('id')); if (empty($this->user)) { - $this->clientError(_('No such user!'), 404, $this->arg('format')); + $this->clientError(_('No such user!'), 404, $this->format); return; } @@ -127,7 +127,7 @@ class ApiTimelineUserAction extends ApiBareAuthAction $suplink = common_local_url('sup', null, null, $this->user->id); header('X-SUP-ID: ' . $suplink); - switch($this->arg('format')) { + switch($this->format) { case 'xml': $this->show_xml_timeline($this->notices); break; diff --git a/lib/apiauth.php b/lib/apiauth.php index 9fc0e57124..25bbae24e5 100644 --- a/lib/apiauth.php +++ b/lib/apiauth.php @@ -172,7 +172,7 @@ class ApiAuthAction extends ApiAction header('HTTP/1.1 401 Unauthorized'); $msg = 'Could not authenticate you.'; - if ($this->arg('format') == 'xml') { + if ($this->format == 'xml') { header('Content-Type: application/xml; charset=utf-8'); $this->startXML(); $this->elementStart('hash'); @@ -180,7 +180,7 @@ class ApiAuthAction extends ApiAction $this->element('request', null, $_SERVER['REQUEST_URI']); $this->elementEnd('hash'); $this->endXML(); - } elseif ($this->arg('format') == 'json') { + } elseif ($this->format == 'json') { header('Content-Type: application/json; charset=utf-8'); $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); From 57dfad64beae100187dcaf3c205645e89611e115 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 9 Oct 2009 17:21:22 -0700 Subject: [PATCH 41/49] Missed some of the references to the old TwitterApiAction - removed --- actions/apiaccountverifycredentials.php | 5 +++-- actions/apifriendshipsexists.php | 2 +- actions/apigrouplistall.php | 2 +- actions/apigroupmembership.php | 2 +- actions/apigroupshow.php | 2 +- actions/apihelptest.php | 2 +- actions/apistatusnetconfig.php | 2 +- actions/apistatusnetversion.php | 2 +- actions/apiusershow.php | 2 +- plugins/Realtime/RealtimePlugin.php | 4 ++-- 10 files changed, 13 insertions(+), 12 deletions(-) diff --git a/actions/apiaccountverifycredentials.php b/actions/apiaccountverifycredentials.php index 104b9867fd..8b976bbf3d 100644 --- a/actions/apiaccountverifycredentials.php +++ b/actions/apiaccountverifycredentials.php @@ -67,8 +67,9 @@ class ApiAccountVerifyCredentialsAction extends ApiAuthAction case 'json': $args['id'] = $this->auth_user->id; $action_obj = new ApiUserShowAction(); - $action_obj->prepare($args); - $action_obj->handle($args); + if ($action_obj->prepare($args)) { + $action_obj->handle($args); + } break; default: header('Content-Type: text/html; charset=utf-8'); diff --git a/actions/apifriendshipsexists.php b/actions/apifriendshipsexists.php index 1ebfc9e8fd..df9f0c949c 100644 --- a/actions/apifriendshipsexists.php +++ b/actions/apifriendshipsexists.php @@ -44,7 +44,7 @@ require_once INSTALLDIR.'/lib/api.php'; * @link http://status.net/ */ -class ApiFriendshipsExistsAction extends TwitterApiAction +class ApiFriendshipsExistsAction extends ApiAction { var $user_a = null; var $user_b = null; diff --git a/actions/apigrouplistall.php b/actions/apigrouplistall.php index a0f04ed760..070927b1ea 100644 --- a/actions/apigrouplistall.php +++ b/actions/apigrouplistall.php @@ -43,7 +43,7 @@ require_once INSTALLDIR . '/lib/api.php'; * @link http://status.net/ */ -class ApiGroupListAllAction extends TwitterApiAction +class ApiGroupListAllAction extends ApiAction { var $page = null; var $count = null; diff --git a/actions/apigroupmembership.php b/actions/apigroupmembership.php index da510ff26b..0e9510d713 100644 --- a/actions/apigroupmembership.php +++ b/actions/apigroupmembership.php @@ -43,7 +43,7 @@ require_once INSTALLDIR . '/lib/api.php'; * @link http://status.net/ */ -class ApiGroupMembershipAction extends TwitterApiAction +class ApiGroupMembershipAction extends ApiAction { var $page = null; var $count = null; diff --git a/actions/apigroupshow.php b/actions/apigroupshow.php index cdaf707aa9..262fe67184 100644 --- a/actions/apigroupshow.php +++ b/actions/apigroupshow.php @@ -43,7 +43,7 @@ require_once INSTALLDIR.'/lib/api.php'; * @link http://status.net/ */ -class ApiGroupShowAction extends TwitterApiAction +class ApiGroupShowAction extends ApiAction { var $group = null; diff --git a/actions/apihelptest.php b/actions/apihelptest.php index ac1bb1a5b3..cd5b86cf93 100644 --- a/actions/apihelptest.php +++ b/actions/apihelptest.php @@ -43,7 +43,7 @@ require_once INSTALLDIR . '/lib/api.php'; * @link http://status.net/ */ -class ApiHelpTestAction extends TwitterApiAction +class ApiHelpTestAction extends ApiAction { /** diff --git a/actions/apistatusnetconfig.php b/actions/apistatusnetconfig.php index 6fb65331f4..356942a859 100644 --- a/actions/apistatusnetconfig.php +++ b/actions/apistatusnetconfig.php @@ -47,7 +47,7 @@ require_once INSTALLDIR . '/lib/api.php'; * @link http://status.net/ */ -class ApiStatusnetConfigAction extends TwitterApiAction +class ApiStatusnetConfigAction extends ApiAction { var $keys = array( 'site' => array('name', 'server', 'theme', 'path', 'fancy', 'language', diff --git a/actions/apistatusnetversion.php b/actions/apistatusnetversion.php index 2cd99edb7a..fb632fd93b 100644 --- a/actions/apistatusnetversion.php +++ b/actions/apistatusnetversion.php @@ -46,7 +46,7 @@ require_once INSTALLDIR . '/lib/api.php'; * @link http://status.net/ */ -class ApiStatusnetVersionAction extends TwitterApiAction +class ApiStatusnetVersionAction extends ApiAction { /** * Take arguments for running diff --git a/actions/apiusershow.php b/actions/apiusershow.php index 1cd0cdfd5f..442efc1943 100644 --- a/actions/apiusershow.php +++ b/actions/apiusershow.php @@ -44,7 +44,7 @@ require_once INSTALLDIR.'/lib/api.php'; * @link http://status.net/ */ -class ApiUserShowAction extends TwitterApiAction +class ApiUserShowAction extends ApiAction { var $user = null; diff --git a/plugins/Realtime/RealtimePlugin.php b/plugins/Realtime/RealtimePlugin.php index 31e75221be..9a750bbc8d 100644 --- a/plugins/Realtime/RealtimePlugin.php +++ b/plugins/Realtime/RealtimePlugin.php @@ -240,11 +240,11 @@ class RealtimePlugin extends Plugin // FIXME: this code should be abstracted to a neutral third // party, like Notice::asJson(). I'm not sure of the ethics // of refactoring from within a plugin, so I'm just abusing - // the TwitterApiAction method. Don't do this unless you're me! + // the ApiAction method. Don't do this unless you're me! require_once(INSTALLDIR.'/lib/api.php'); - $act = new TwitterApiAction('/dev/null'); + $act = new ApiAction('/dev/null'); $arr = $act->twitter_status_array($notice, true); $arr['url'] = $notice->bestUrl(); From b08d16ef2bf5995ca2feee2d2688e0080eaf5124 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 9 Oct 2009 17:32:53 -0700 Subject: [PATCH 42/49] These same params are used in most API actions; moved to base API class --- actions/apidirectmessage.php | 11 ----------- actions/apigrouplist.php | 12 ------------ actions/apigrouplistall.php | 11 ----------- actions/apigroupmembership.php | 14 +------------- actions/apisubscriptions.php | 5 ----- actions/apitimelinefavorites.php | 13 ------------- actions/apitimelinefriends.php | 12 ------------ actions/apitimelinegroup.php | 9 +-------- actions/apitimelinementions.php | 6 ------ actions/apitimelinepublic.php | 6 ------ actions/apitimelinetag.php | 5 +---- actions/apitimelineuser.php | 6 ------ lib/api.php | 17 +++++++++++++++-- 13 files changed, 18 insertions(+), 109 deletions(-) diff --git a/actions/apidirectmessage.php b/actions/apidirectmessage.php index cede4c0721..f0013c54c5 100644 --- a/actions/apidirectmessage.php +++ b/actions/apidirectmessage.php @@ -46,11 +46,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiDirectMessageAction extends ApiAuthAction { var $messages = null; - var $page = null; - var $count = null; - var $max_id = null; - var $since_id = null; - var $since = null; var $title = null; var $subtitle = null; var $link = null; @@ -77,12 +72,6 @@ class ApiDirectMessageAction extends ApiAuthAction return; } - $this->page = (int)$this->arg('page', 1); - $this->count = (int)$this->arg('count', 20); - $this->max_id = (int)$this->arg('max_id', 0); - $this->since_id = (int)$this->arg('since_id', 0); - $this->since = $this->arg('since'); - $server = common_root_url(); $taguribase = common_config('integration', 'taguri'); diff --git a/actions/apigrouplist.php b/actions/apigrouplist.php index 00ceeed760..7a5aab72eb 100644 --- a/actions/apigrouplist.php +++ b/actions/apigrouplist.php @@ -45,12 +45,6 @@ require_once INSTALLDIR . '/lib/apibareauth.php'; class ApiGroupListAction extends ApiBareAuthAction { - var $user = null; - var $page = null; - var $count = null; - var $max_id = null; - var $since_id = null; - var $since = null; var $groups = null; /** @@ -65,12 +59,6 @@ class ApiGroupListAction extends ApiBareAuthAction function prepare($args) { parent::prepare($args); - - $this->page = (int)$this->arg('page', 1); - $this->count = (int)$this->arg('count', 20); - $this->max_id = (int)$this->arg('max_id', 0); - $this->since_id = (int)$this->arg('since_id', 0); - $this->since = $this->arg('since'); $this->user = $this->getTargetUser($id); $this->groups = $this->getGroups(); diff --git a/actions/apigrouplistall.php b/actions/apigrouplistall.php index 070927b1ea..3e236816ab 100644 --- a/actions/apigrouplistall.php +++ b/actions/apigrouplistall.php @@ -45,11 +45,6 @@ require_once INSTALLDIR . '/lib/api.php'; class ApiGroupListAllAction extends ApiAction { - var $page = null; - var $count = null; - var $max_id = null; - var $since_id = null; - var $since = null; var $groups = null; /** @@ -65,12 +60,6 @@ class ApiGroupListAllAction extends ApiAction { parent::prepare($args); - $this->page = (int)$this->arg('page', 1); - $this->count = (int)$this->arg('count', 20); - $this->max_id = (int)$this->arg('max_id', 0); - $this->since_id = (int)$this->arg('since_id', 0); - $this->since = $this->arg('since'); - $this->user = $this->getTargetUser($id); $this->groups = $this->getGroups(); diff --git a/actions/apigroupmembership.php b/actions/apigroupmembership.php index 0e9510d713..0bc846d604 100644 --- a/actions/apigroupmembership.php +++ b/actions/apigroupmembership.php @@ -45,11 +45,6 @@ require_once INSTALLDIR . '/lib/api.php'; class ApiGroupMembershipAction extends ApiAction { - var $page = null; - var $count = null; - var $max_id = null; - var $since_id = null; - var $since = null; var $group = null; var $profiles = null; @@ -66,14 +61,7 @@ class ApiGroupMembershipAction extends ApiAction { parent::prepare($args); - $this->page = (int)$this->arg('page', 1); - $this->count = (int)$this->arg('count', 20); - $this->max_id = (int)$this->arg('max_id', 0); - $this->since_id = (int)$this->arg('since_id', 0); - $this->since = $this->arg('since'); - - $this->group = $this->getTargetGroup($this->arg('id')); - + $this->group = $this->getTargetGroup($this->arg('id')); $this->profiles = $this->getProfiles(); return true; diff --git a/actions/apisubscriptions.php b/actions/apisubscriptions.php index 9dbddbd9bd..1332fd71c6 100644 --- a/actions/apisubscriptions.php +++ b/actions/apisubscriptions.php @@ -47,10 +47,6 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; class ApiSubscriptionsAction extends ApiBareAuthAction { - - var $page = null; - var $count = null; - var $user = null; var $profiles = null; var $tag = null; var $lite = null; @@ -69,7 +65,6 @@ class ApiSubscriptionsAction extends ApiBareAuthAction { parent::prepare($args); - $this->page = (int)$this->arg('page', 1); $this->tag = $this->arg('tag'); // Note: Twitter no longer supports 'lite' diff --git a/actions/apitimelinefavorites.php b/actions/apitimelinefavorites.php index 231f2ae49c..d35e051835 100644 --- a/actions/apitimelinefavorites.php +++ b/actions/apitimelinefavorites.php @@ -46,14 +46,7 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; class ApiTimelineFavoritesAction extends ApiBareAuthAction { - - var $user = null; var $notices = null; - var $page = null; - var $count = null; - var $max_id = null; - var $since_id = null; - var $since = null; /** * Take arguments for running @@ -68,12 +61,6 @@ class ApiTimelineFavoritesAction extends ApiBareAuthAction { parent::prepare($args); - $this->page = (int)$this->arg('page', 1); - $this->count = (int)$this->arg('count', 20); - $this->max_id = (int)$this->arg('max_id', 0); - $this->since_id = (int)$this->arg('since_id', 0); - $this->since = $this->arg('since'); - $this->user = $this->getTargetUser($this->arg('id')); if (empty($this->user)) { diff --git a/actions/apitimelinefriends.php b/actions/apitimelinefriends.php index 02e3525695..544824078e 100644 --- a/actions/apitimelinefriends.php +++ b/actions/apitimelinefriends.php @@ -46,13 +46,7 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; class ApiTimelineFriendsAction extends ApiBareAuthAction { - - var $user = null; var $notices = null; - var $count = null; - var $max_id = null; - var $since_id = null; - var $since = null; /** * Take arguments for running @@ -67,12 +61,6 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction { parent::prepare($args); - $this->page = (int)$this->arg('page', 1); - $this->count = (int)$this->arg('count', 20); - $this->max_id = (int)$this->arg('max_id', 0); - $this->since_id = (int)$this->arg('since_id', 0); - $this->since = $this->arg('since'); - $this->user = $this->getTargetUser($this->arg('id')); if (empty($this->user)) { diff --git a/actions/apitimelinegroup.php b/actions/apitimelinegroup.php index abe7f0c5d8..6f2043fb65 100644 --- a/actions/apitimelinegroup.php +++ b/actions/apitimelinegroup.php @@ -62,14 +62,7 @@ class ApiTimelineGroupAction extends ApiAction { parent::prepare($args); - $this->page = (int)$this->arg('page', 1); - $this->count = (int)$this->arg('count', 20); - $this->max_id = (int)$this->arg('max_id', 0); - $this->since_id = (int)$this->arg('since_id', 0); - $this->since = $this->arg('since'); - - $this->group = $this->getTargetGroup($this->arg('id')); - + $this->group = $this->getTargetGroup($this->arg('id')); $this->notices = $this->getNotices(); return true; diff --git a/actions/apitimelinementions.php b/actions/apitimelinementions.php index 7549b4722d..60669d9ba3 100644 --- a/actions/apitimelinementions.php +++ b/actions/apitimelinementions.php @@ -62,12 +62,6 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction { parent::prepare($args); - $this->page = (int)$this->arg('page', 1); - $this->count = (int)$this->arg('count', 20); - $this->max_id = (int)$this->arg('max_id', 0); - $this->since_id = (int)$this->arg('since_id', 0); - $this->since = $this->arg('since'); - $this->user = $this->getTargetUser($this->arg('id')); if (empty($this->user)) { diff --git a/actions/apitimelinepublic.php b/actions/apitimelinepublic.php index a635ddc91e..b992136d1f 100644 --- a/actions/apitimelinepublic.php +++ b/actions/apitimelinepublic.php @@ -61,12 +61,6 @@ class ApiTimelinePublicAction extends ApiAction { parent::prepare($args); - $this->page = (int)$this->arg('page', 1); - $this->count = (int)$this->arg('count', 20); - $this->max_id = (int)$this->arg('max_id', 0); - $this->since_id = (int)$this->arg('since_id', 0); - $this->since = $this->arg('since'); - $this->notices = $this->getNotices(); return true; diff --git a/actions/apitimelinetag.php b/actions/apitimelinetag.php index 8211b01226..53e79e4b9e 100644 --- a/actions/apitimelinetag.php +++ b/actions/apitimelinetag.php @@ -61,10 +61,7 @@ class ApiTimelineTagAction extends ApiAction { parent::prepare($args); - $this->page = (int)$this->arg('page', 1); - $this->count = (int)$this->arg('count', 20); - $this->tag = $this->arg('tag'); - + $this->tag = $this->arg('tag'); $this->notices = $this->getNotices(); return true; diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php index 81e23116b7..652a1b0d95 100644 --- a/actions/apitimelineuser.php +++ b/actions/apitimelineuser.php @@ -64,12 +64,6 @@ class ApiTimelineUserAction extends ApiBareAuthAction { parent::prepare($args); - $this->page = (int)$this->arg('page', 1); - $this->count = (int)$this->arg('count', 20); - $this->max_id = (int)$this->arg('max_id', 0); - $this->since_id = (int)$this->arg('since_id', 0); - $this->since = $this->arg('since'); - $this->user = $this->getTargetUser($this->arg('id')); if (empty($this->user)) { diff --git a/lib/api.php b/lib/api.php index 3afb20612d..95a0779add 100644 --- a/lib/api.php +++ b/lib/api.php @@ -43,8 +43,14 @@ if (!defined('STATUSNET')) { class ApiAction extends Action { - var $format = null; - + var $format = null; + var $user = null; + var $page = null; + var $count = null; + var $max_id = null; + var $since_id = null; + var $since = null; + /** * Initialization. * @@ -56,7 +62,14 @@ class ApiAction extends Action function prepare($args) { parent::prepare($args); + $this->format = $this->arg('format'); + $this->page = (int)$this->arg('page', 1); + $this->count = (int)$this->arg('count', 20); + $this->max_id = (int)$this->arg('max_id', 0); + $this->since_id = (int)$this->arg('since_id', 0); + $this->since = $this->arg('since'); + return true; } From 061af8fa06ccb98f667d1ee670da2dbb179d8b0e Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 9 Oct 2009 17:53:35 -0700 Subject: [PATCH 43/49] CamelCase all function names in the API code --- actions/apiaccountratelimitstatus.php | 4 +- actions/apiblockcreate.php | 6 +- actions/apiblockdestroy.php | 6 +- actions/apidirectmessage.php | 20 +- actions/apifavoritecreate.php | 2 +- actions/apifavoritedestroy.php | 2 +- actions/apifriendshipscreate.php | 6 +- actions/apifriendshipsdestroy.php | 6 +- actions/apifriendshipsexists.php | 8 +- actions/apifriendshipsshow.php | 12 +- actions/apigroupismember.php | 10 +- actions/apigroupjoin.php | 2 +- actions/apigroupleave.php | 2 +- actions/apigrouplist.php | 8 +- actions/apigrouplistall.php | 8 +- actions/apigroupmembership.php | 4 +- actions/apigroupshow.php | 2 +- actions/apihelptest.php | 8 +- actions/apistatusesdestroy.php | 4 +- actions/apistatusesshow.php | 2 +- actions/apistatusesupdate.php | 2 +- actions/apistatusnetconfig.php | 10 +- actions/apistatusnetversion.php | 8 +- actions/apisubscriptions.php | 8 +- actions/apitimelinefavorites.php | 8 +- actions/apitimelinefriends.php | 8 +- actions/apitimelinegroup.php | 8 +- actions/apitimelinementions.php | 8 +- actions/apitimelinepublic.php | 8 +- actions/apitimelinetag.php | 8 +- actions/apitimelineuser.php | 8 +- actions/apiusershow.php | 14 +- actions/twitapisearchatom.php | 2 +- actions/twitapisearchjson.php | 4 +- lib/api.php | 295 ++++++++++++-------------- lib/twitter.php | 4 +- plugins/Realtime/RealtimePlugin.php | 2 +- 37 files changed, 255 insertions(+), 272 deletions(-) diff --git a/actions/apiaccountratelimitstatus.php b/actions/apiaccountratelimitstatus.php index b823e1cd2b..af86dae6a9 100644 --- a/actions/apiaccountratelimitstatus.php +++ b/actions/apiaccountratelimitstatus.php @@ -73,7 +73,7 @@ class ApiAccountRateLimitStatusAction extends ApiBareAuthAction $reset = new DateTime(); $reset->modify('+1 hour'); - $this->init_document($this->format); + $this->initDocument($this->format); if ($this->format == 'xml') { $this->elementStart('hash'); @@ -101,7 +101,7 @@ class ApiAccountRateLimitStatusAction extends ApiBareAuthAction print json_encode($out); } - $this->end_document($this->format); + $this->endDocument($this->format); } } diff --git a/actions/apiblockcreate.php b/actions/apiblockcreate.php index 6dd28dd5ef..e003e5ee96 100644 --- a/actions/apiblockcreate.php +++ b/actions/apiblockcreate.php @@ -100,9 +100,9 @@ class ApiBlockCreateAction extends ApiAuthAction if ($this->user->hasBlocked($this->other) || $this->user->block($this->other) ) { - $this->init_document($this->format); - $this->show_profile($this->other, $this->format); - $this->end_document($this->format); + $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 index a869dfe466..470b60ea53 100644 --- a/actions/apiblockdestroy.php +++ b/actions/apiblockdestroy.php @@ -99,9 +99,9 @@ class ApiBlockDestroyAction extends ApiAuthAction if (!$this->user->hasBlocked($this->other) || $this->user->unblock($this->other) ) { - $this->init_document($this->format); - $this->show_profile($this->other, $this->format); - $this->end_document($this->format); + $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 index f0013c54c5..4e55886d95 100644 --- a/actions/apidirectmessage.php +++ b/actions/apidirectmessage.php @@ -230,7 +230,7 @@ class ApiDirectMessageAction extends ApiAuthAction function showXmlDirectMessages() { - $this->init_document('xml'); + $this->initDocument('xml'); $this->elementStart('direct-messages', array('type' => 'array')); foreach ($this->messages as $m) { @@ -239,7 +239,7 @@ class ApiDirectMessageAction extends ApiAuthAction } $this->elementEnd('direct-messages'); - $this->end_document('xml'); + $this->endDocument('xml'); } /** @@ -250,7 +250,7 @@ class ApiDirectMessageAction extends ApiAuthAction function showJsonDirectMessages() { - $this->init_document('json'); + $this->initDocument('json'); $dmsgs = array(); @@ -259,8 +259,8 @@ class ApiDirectMessageAction extends ApiAuthAction array_push($dmsgs, $dm_array); } - $this->show_json_objects($dmsgs); - $this->end_document('json'); + $this->showJsonObjects($dmsgs); + $this->endDocument('json'); } /** @@ -271,7 +271,7 @@ class ApiDirectMessageAction extends ApiAuthAction function showRssDirectMessages() { - $this->init_document('rss'); + $this->initDocument('rss'); $this->element('title', null, $this->title); @@ -292,10 +292,10 @@ class ApiDirectMessageAction extends ApiAuthAction foreach ($this->messages as $m) { $entry = $this->rssDirectMessageArray($m); - $this->show_twitter_rss_item($entry); + $this->showTwitterRssItem($entry); } - $this->end_twitter_rss(); + $this->endTwitterRss(); } /** @@ -306,7 +306,7 @@ class ApiDirectMessageAction extends ApiAuthAction function showAtomDirectMessages() { - $this->init_document('atom'); + $this->initDocument('atom'); $this->element('title', null, $this->title); $this->element('id', null, $this->id); @@ -334,7 +334,7 @@ class ApiDirectMessageAction extends ApiAuthAction $this->showTwitterAtomEntry($entry); } - $this->end_document('atom'); + $this->endDocument('atom'); } /** diff --git a/actions/apifavoritecreate.php b/actions/apifavoritecreate.php index db001561ec..1b05eb95c9 100644 --- a/actions/apifavoritecreate.php +++ b/actions/apifavoritecreate.php @@ -135,7 +135,7 @@ class ApiFavoriteCreateAction extends ApiAuthAction $this->user->blowFavesCache(); if ($this->format == 'xml') { - $this->show_single_xml_status($this->notice); + $this->showSingleXmlStatus($this->notice); } elseif ($this->format == 'json') { $this->show_single_json_status($this->notice); } diff --git a/actions/apifavoritedestroy.php b/actions/apifavoritedestroy.php index 3640459f99..aac866d7e9 100644 --- a/actions/apifavoritedestroy.php +++ b/actions/apifavoritedestroy.php @@ -138,7 +138,7 @@ class ApiFavoriteDestroyAction extends ApiAuthAction $this->user->blowFavesCache(); if ($this->format == 'xml') { - $this->show_single_xml_status($this->notice); + $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 index 85eaf3a296..6c44d79610 100644 --- a/actions/apifriendshipscreate.php +++ b/actions/apifriendshipscreate.php @@ -126,9 +126,9 @@ class ApiFriendshipsCreateAction extends ApiAuthAction return; } - $this->init_document($this->format); - $this->show_profile($this->other, $this->format); - $this->end_document($this->format); + $this->initDocument($this->format); + $this->showProfile($this->other, $this->format); + $this->endDocument($this->format); } } diff --git a/actions/apifriendshipsdestroy.php b/actions/apifriendshipsdestroy.php index 2743780519..a15f202aa8 100644 --- a/actions/apifriendshipsdestroy.php +++ b/actions/apifriendshipsdestroy.php @@ -128,9 +128,9 @@ class ApiFriendshipsDestroyAction extends ApiAuthAction return; } - $this->init_document($this->format); - $this->show_profile($this->other, $this->format); - $this->end_document($this->format); + $this->initDocument($this->format); + $this->showProfile($this->other, $this->format); + $this->endDocument($this->format); } } diff --git a/actions/apifriendshipsexists.php b/actions/apifriendshipsexists.php index df9f0c949c..93be5f84ea 100644 --- a/actions/apifriendshipsexists.php +++ b/actions/apifriendshipsexists.php @@ -107,14 +107,14 @@ class ApiFriendshipsExistsAction extends ApiAction switch ($this->format) { case 'xml': - $this->init_document('xml'); + $this->initDocument('xml'); $this->element('friends', null, $result); - $this->end_document('xml'); + $this->endDocument('xml'); break; case 'json': - $this->init_document('json'); + $this->initDocument('json'); print json_encode($result); - $this->end_document('json'); + $this->endDocument('json'); break; default: break; diff --git a/actions/apifriendshipsshow.php b/actions/apifriendshipsshow.php index 0ae6a7b82b..8850496c79 100644 --- a/actions/apifriendshipsshow.php +++ b/actions/apifriendshipsshow.php @@ -143,18 +143,18 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction return; } - $result = $this->twitter_relationship_array($this->source, $this->target); + $result = $this->twitterRelationshipArray($this->source, $this->target); switch ($this->format) { case 'xml': - $this->init_document('xml'); - $this->show_twitter_xml_relationship($result[relationship]); - $this->end_document('xml'); + $this->initDocument('xml'); + $this->showTwitterXmlRelationship($result[relationship]); + $this->endDocument('xml'); break; case 'json': - $this->init_document('json'); + $this->initDocument('json'); print json_encode($result); - $this->end_document('json'); + $this->endDocument('json'); break; default: break; diff --git a/actions/apigroupismember.php b/actions/apigroupismember.php index 359b7ca4fa..6cf3270129 100644 --- a/actions/apigroupismember.php +++ b/actions/apigroupismember.php @@ -95,14 +95,14 @@ class ApiGroupIsMemberAction extends ApiBareAuthAction switch($this->format) { case 'xml': - $this->init_document('xml'); + $this->initDocument('xml'); $this->element('is_member', null, $is_member); - $this->end_document('xml'); + $this->endDocument('xml'); break; case 'json': - $this->init_document('json'); - $this->show_json_objects(array('is_member' => $is_member)); - $this->end_document('json'); + $this->initDocument('json'); + $this->showJsonObjects(array('is_member' => $is_member)); + $this->endDocument('json'); break; default: $this->clientError( diff --git a/actions/apigroupjoin.php b/actions/apigroupjoin.php index e51842bcb6..f930aa5190 100644 --- a/actions/apigroupjoin.php +++ b/actions/apigroupjoin.php @@ -143,7 +143,7 @@ class ApiGroupJoinAction extends ApiAuthAction $this->show_single_xml_group($this->group); break; case 'json': - $this->show_single_json_group($this->group); + $this->showSingleJsonGroup($this->group); break; default: $this->clientError( diff --git a/actions/apigroupleave.php b/actions/apigroupleave.php index 332bd7b7b2..4e3192ac08 100644 --- a/actions/apigroupleave.php +++ b/actions/apigroupleave.php @@ -129,7 +129,7 @@ class ApiGroupLeaveAction extends ApiAuthAction $this->show_single_xml_group($this->group); break; case 'json': - $this->show_single_json_group($this->group); + $this->showSingleJsonGroup($this->group); break; default: $this->clientError( diff --git a/actions/apigrouplist.php b/actions/apigrouplist.php index 7a5aab72eb..1fc31831a0 100644 --- a/actions/apigrouplist.php +++ b/actions/apigrouplist.php @@ -101,15 +101,15 @@ class ApiGroupListAction extends ApiBareAuthAction switch($this->format) { case 'xml': - $this->show_xml_groups($this->groups); + $this->showXmlGroups($this->groups); break; case 'rss': - $this->show_rss_groups($this->groups, $title, $link, $subtitle); + $this->showRssGroups($this->groups, $title, $link, $subtitle); break; case 'atom': $selfuri = common_root_url() . 'api/statusnet/groups/list/' . $this->user->id . '.atom'; - $this->show_atom_groups( + $this->showAtomGroups( $this->groups, $title, $id, @@ -119,7 +119,7 @@ class ApiGroupListAction extends ApiBareAuthAction ); break; case 'json': - $this->show_json_groups($this->groups); + $this->showJsonGroups($this->groups); break; default: $this->clientError( diff --git a/actions/apigrouplistall.php b/actions/apigrouplistall.php index 3e236816ab..ef96a08bdd 100644 --- a/actions/apigrouplistall.php +++ b/actions/apigrouplistall.php @@ -89,15 +89,15 @@ class ApiGroupListAllAction extends ApiAction switch($this->format) { case 'xml': - $this->show_xml_groups($this->groups); + $this->showXmlGroups($this->groups); break; case 'rss': - $this->show_rss_groups($this->groups, $title, $link, $subtitle); + $this->showRssGroups($this->groups, $title, $link, $subtitle); break; case 'atom': $selfuri = common_root_url() . 'api/statusnet/groups/list_all.atom'; - $this->show_atom_groups( + $this->showAtomGroups( $this->groups, $title, $id, @@ -107,7 +107,7 @@ class ApiGroupListAllAction extends ApiAction ); break; case 'json': - $this->show_json_groups($this->groups); + $this->showJsonGroups($this->groups); break; default: $this->clientError( diff --git a/actions/apigroupmembership.php b/actions/apigroupmembership.php index 0bc846d604..27f77029eb 100644 --- a/actions/apigroupmembership.php +++ b/actions/apigroupmembership.php @@ -85,10 +85,10 @@ class ApiGroupMembershipAction extends ApiAction switch($this->format) { case 'xml': - $this->show_twitter_xml_users($this->profiles); + $this->showTwitterXmlUsers($this->profiles); break; case 'json': - $this->show_json_users($this->profiles); + $this->showJsonUsers($this->profiles); break; default: $this->clientError( diff --git a/actions/apigroupshow.php b/actions/apigroupshow.php index 262fe67184..8969ae194b 100644 --- a/actions/apigroupshow.php +++ b/actions/apigroupshow.php @@ -93,7 +93,7 @@ class ApiGroupShowAction extends ApiAction $this->show_single_xml_group($this->group); break; case 'json': - $this->show_single_json_group($this->group); + $this->showSingleJsonGroup($this->group); break; default: $this->clientError(_('API method not found!'), 404, $this->format); diff --git a/actions/apihelptest.php b/actions/apihelptest.php index cd5b86cf93..4691cbf99c 100644 --- a/actions/apihelptest.php +++ b/actions/apihelptest.php @@ -74,13 +74,13 @@ class ApiHelpTestAction extends ApiAction parent::handle($args); if ($this->format == 'xml') { - $this->init_document('xml'); + $this->initDocument('xml'); $this->element('ok', null, 'true'); - $this->end_document('xml'); + $this->endDocument('xml'); } elseif ($this->format == 'json') { - $this->init_document('json'); + $this->initDocument('json'); print '"ok"'; - $this->end_document('json'); + $this->endDocument('json'); } else { $this->clientError( _('API method not found!'), diff --git a/actions/apistatusesdestroy.php b/actions/apistatusesdestroy.php index 7680f96dcf..74a1310a22 100644 --- a/actions/apistatusesdestroy.php +++ b/actions/apistatusesdestroy.php @@ -112,7 +112,7 @@ class ApiStatusesDestroyAction extends ApiAuthAction $this->notice->delete(); if ($this->format == 'xml') { - $this->show_single_xml_status($this->notice); + $this->showSingleXmlStatus($this->notice); } elseif ($this->format == 'json') { $this->show_single_json_status($this->notice); } @@ -134,7 +134,7 @@ class ApiStatusesDestroyAction extends ApiAuthAction { if (!empty($this->notice)) { if ($this->format == 'xml') { - $this->show_single_xml_status($this->notice); + $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 index 0096cfe6b9..5d32a0bfc3 100644 --- a/actions/apistatusesshow.php +++ b/actions/apistatusesshow.php @@ -110,7 +110,7 @@ class ApiStatusesShowAction extends ApiAction { if (!empty($this->notice)) { if ($this->format == 'xml') { - $this->show_single_xml_status($this->notice); + $this->showSingleXmlStatus($this->notice); } elseif ($this->format == 'json') { $this->show_single_json_status($this->notice); } diff --git a/actions/apistatusesupdate.php b/actions/apistatusesupdate.php index 7d6a574ef0..479654be8f 100644 --- a/actions/apistatusesupdate.php +++ b/actions/apistatusesupdate.php @@ -201,7 +201,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction { if (!empty($this->notice)) { if ($this->format == 'xml') { - $this->show_single_xml_status($this->notice); + $this->showSingleXmlStatus($this->notice); } elseif ($this->format == 'json') { $this->show_single_json_status($this->notice); } diff --git a/actions/apistatusnetconfig.php b/actions/apistatusnetconfig.php index 356942a859..a93570698d 100644 --- a/actions/apistatusnetconfig.php +++ b/actions/apistatusnetconfig.php @@ -88,7 +88,7 @@ class ApiStatusnetConfigAction extends ApiAction switch ($this->format) { case 'xml': - $this->init_document('xml'); + $this->initDocument('xml'); $this->elementStart('config'); // XXX: check that all sections and settings are legal XML elements @@ -111,7 +111,7 @@ class ApiStatusnetConfigAction extends ApiAction $this->elementEnd($section); } $this->elementEnd('config'); - $this->end_document('xml'); + $this->endDocument('xml'); break; case 'json': $result = array(); @@ -122,9 +122,9 @@ class ApiStatusnetConfigAction extends ApiAction = common_config($section, $setting); } } - $this->init_document('json'); - $this->show_json_objects($result); - $this->end_document('json'); + $this->initDocument('json'); + $this->showJsonObjects($result); + $this->endDocument('json'); break; default: $this->clientError( diff --git a/actions/apistatusnetversion.php b/actions/apistatusnetversion.php index fb632fd93b..6af9bdd1a1 100644 --- a/actions/apistatusnetversion.php +++ b/actions/apistatusnetversion.php @@ -77,14 +77,14 @@ class ApiStatusnetVersionAction extends ApiAction switch ($this->format) { case 'xml': - $this->init_document('xml'); + $this->initDocument('xml'); $this->element('version', null, STATUSNET_VERSION); - $this->end_document('xml'); + $this->endDocument('xml'); break; case 'json': - $this->init_document('json'); + $this->initDocument('json'); print '"'.STATUSNET_VERSION.'"'; - $this->end_document('json'); + $this->endDocument('json'); break; default: $this->clientError( diff --git a/actions/apisubscriptions.php b/actions/apisubscriptions.php index 1332fd71c6..a952e20b87 100644 --- a/actions/apisubscriptions.php +++ b/actions/apisubscriptions.php @@ -108,7 +108,7 @@ class ApiSubscriptionsAction extends ApiBareAuthAction return; } - $this->init_document($this->format); + $this->initDocument($this->format); if (isset($this->ids_only)) { $this->showIds(); @@ -116,7 +116,7 @@ class ApiSubscriptionsAction extends ApiBareAuthAction $this->showProfiles(isset($this->lite) ? false : true); } - $this->end_document($this->format); + $this->endDocument($this->format); } /** @@ -204,7 +204,7 @@ class ApiSubscriptionsAction extends ApiBareAuthAction case 'xml': $this->elementStart('users', array('type' => 'array')); foreach ($this->profiles as $profile) { - $this->show_profile( + $this->showProfile( $profile, $this->format, null, @@ -216,7 +216,7 @@ class ApiSubscriptionsAction extends ApiBareAuthAction case 'json': $arrays = array(); foreach ($this->profiles as $profile) { - $arrays[] = $this->twitter_user_array( + $arrays[] = $this->twitterUserArray( $profile, $include_statuses ); diff --git a/actions/apitimelinefavorites.php b/actions/apitimelinefavorites.php index d35e051835..c85e56264d 100644 --- a/actions/apitimelinefavorites.php +++ b/actions/apitimelinefavorites.php @@ -121,21 +121,21 @@ class ApiTimelineFavoritesAction extends ApiBareAuthAction switch($this->format) { case 'xml': - $this->show_xml_timeline($this->notices); + $this->showXmlTimeline($this->notices); break; case 'rss': - $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + $this->showRssTimeline($this->notices, $title, $link, $subtitle); break; case 'atom': $selfuri = common_root_url() . ltrim($_SERVER['QUERY_STRING'], 'p='); - $this->show_atom_timeline( + $this->showAtomTimeline( $this->notices, $title, $id, $link, $subtitle, null, $selfuri ); break; case 'json': - $this->show_json_timeline($this->notices); + $this->showJsonTimeline($this->notices); break; default: $this->clientError(_('API method not found!'), $code = 404); diff --git a/actions/apitimelinefriends.php b/actions/apitimelinefriends.php index 544824078e..90f3b3c064 100644 --- a/actions/apitimelinefriends.php +++ b/actions/apitimelinefriends.php @@ -112,10 +112,10 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction switch($this->format) { case 'xml': - $this->show_xml_timeline($this->notices); + $this->showXmlTimeline($this->notices); break; case 'rss': - $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + $this->showRssTimeline($this->notices, $title, $link, $subtitle); break; case 'atom': @@ -130,13 +130,13 @@ class ApiTimelineFriendsAction extends ApiBareAuthAction 'api/statuses/friends_timeline.atom'; } - $this->show_atom_timeline( + $this->showAtomTimeline( $this->notices, $title, $id, $link, $subtitle, null, $selfuri ); break; case 'json': - $this->show_json_timeline($this->notices); + $this->showJsonTimeline($this->notices); break; default: $this->clientError(_('API method not found!'), $code = 404); diff --git a/actions/apitimelinegroup.php b/actions/apitimelinegroup.php index 6f2043fb65..2a6f35d728 100644 --- a/actions/apitimelinegroup.php +++ b/actions/apitimelinegroup.php @@ -108,16 +108,16 @@ class ApiTimelineGroupAction extends ApiAction switch($this->format) { case 'xml': - $this->show_xml_timeline($this->notices); + $this->showXmlTimeline($this->notices); break; case 'rss': - $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + $this->showRssTimeline($this->notices, $title, $link, $subtitle); break; case 'atom': $selfuri = common_root_url() . 'api/statusnet/groups/timeline/' . $this->group->nickname . '.atom'; - $this->show_atom_timeline( + $this->showAtomTimeline( $this->notices, $title, $id, @@ -128,7 +128,7 @@ class ApiTimelineGroupAction extends ApiAction ); break; case 'json': - $this->show_json_timeline($this->notices); + $this->showJsonTimeline($this->notices); break; default: $this->clientError( diff --git a/actions/apitimelinementions.php b/actions/apitimelinementions.php index 60669d9ba3..c25fb0a0e9 100644 --- a/actions/apitimelinementions.php +++ b/actions/apitimelinementions.php @@ -118,21 +118,21 @@ class ApiTimelineMentionsAction extends ApiBareAuthAction switch($this->format) { case 'xml': - $this->show_xml_timeline($this->notices); + $this->showXmlTimeline($this->notices); break; case 'rss': - $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + $this->showRssTimeline($this->notices, $title, $link, $subtitle); break; case 'atom': $selfuri = common_root_url() . ltrim($_SERVER['QUERY_STRING'], 'p='); - $this->show_atom_timeline( + $this->showAtomTimeline( $this->notices, $title, $id, $link, $subtitle, null, $selfuri ); break; case 'json': - $this->show_json_timeline($this->notices); + $this->showJsonTimeline($this->notices); break; default: $this->clientError(_('API method not found!'), $code = 404); diff --git a/actions/apitimelinepublic.php b/actions/apitimelinepublic.php index b992136d1f..4bff4adb60 100644 --- a/actions/apitimelinepublic.php +++ b/actions/apitimelinepublic.php @@ -99,20 +99,20 @@ class ApiTimelinePublicAction extends ApiAction switch($this->format) { case 'xml': - $this->show_xml_timeline($this->notices); + $this->showXmlTimeline($this->notices); break; case 'rss': - $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + $this->showRssTimeline($this->notices, $title, $link, $subtitle); break; case 'atom': $selfuri = common_root_url() . 'api/statuses/public_timeline.atom'; - $this->show_atom_timeline( + $this->showAtomTimeline( $this->notices, $title, $id, $link, $subtitle, null, $selfuri ); break; case 'json': - $this->show_json_timeline($this->notices); + $this->showJsonTimeline($this->notices); break; default: $this->clientError(_('API method not found!'), $code = 404); diff --git a/actions/apitimelinetag.php b/actions/apitimelinetag.php index 53e79e4b9e..cf211b173c 100644 --- a/actions/apitimelinetag.php +++ b/actions/apitimelinetag.php @@ -107,16 +107,16 @@ class ApiTimelineTagAction extends ApiAction switch($this->format) { case 'xml': - $this->show_xml_timeline($this->notices); + $this->showXmlTimeline($this->notices); break; case 'rss': - $this->show_rss_timeline($this->notices, $title, $link, $subtitle); + $this->showRssTimeline($this->notices, $title, $link, $subtitle); break; case 'atom': $selfuri = common_root_url() . 'api/statusnet/tags/timeline/' . $this->tag . '.atom'; - $this->show_atom_timeline( + $this->showAtomTimeline( $this->notices, $title, $id, @@ -127,7 +127,7 @@ class ApiTimelineTagAction extends ApiAction ); break; case 'json': - $this->show_json_timeline($this->notices); + $this->showJsonTimeline($this->notices); break; default: $this->clientError(_('API method not found!'), $code = 404); diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php index 652a1b0d95..e7fac3e7a2 100644 --- a/actions/apitimelineuser.php +++ b/actions/apitimelineuser.php @@ -123,10 +123,10 @@ class ApiTimelineUserAction extends ApiBareAuthAction switch($this->format) { case 'xml': - $this->show_xml_timeline($this->notices); + $this->showXmlTimeline($this->notices); break; case 'rss': - $this->show_rss_timeline( + $this->showRssTimeline( $this->notices, $title, $link, $subtitle, $suplink ); @@ -140,13 +140,13 @@ class ApiTimelineUserAction extends ApiBareAuthAction $selfuri = common_root_url() . 'api/statuses/user_timeline.atom'; } - $this->show_atom_timeline( + $this->showAtomTimeline( $this->notices, $title, $id, $link, $subtitle, $suplink, $selfuri ); break; case 'json': - $this->show_json_timeline($this->notices); + $this->showJsonTimeline($this->notices); break; default: $this->clientError(_('API method not found!'), $code = 404); diff --git a/actions/apiusershow.php b/actions/apiusershow.php index 442efc1943..d07040a43d 100644 --- a/actions/apiusershow.php +++ b/actions/apiusershow.php @@ -105,16 +105,16 @@ class ApiUserShowAction extends ApiAction return; } - $twitter_user = $this->twitter_user_array($this->user->getProfile(), true); + $twitter_user = $this->twitterUserArray($this->user->getProfile(), true); if ($this->format == 'xml') { - $this->init_document('xml'); - $this->show_twitter_xml_user($twitter_user); - $this->end_document('xml'); + $this->initDocument('xml'); + $this->showTwitterXmlUser($twitter_user); + $this->endDocument('xml'); } elseif ($this->format == 'json') { - $this->init_document('json'); - $this->show_json_objects($twitter_user); - $this->end_document('json'); + $this->initDocument('json'); + $this->showJsonObjects($twitter_user); + $this->endDocument('json'); } } diff --git a/actions/twitapisearchatom.php b/actions/twitapisearchatom.php index 0ef9d28260..7d618c471f 100644 --- a/actions/twitapisearchatom.php +++ b/actions/twitapisearchatom.php @@ -340,7 +340,7 @@ class TwitapisearchatomAction extends ApiAction // 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 5abff6496e..c7fa741a06 100644 --- a/actions/twitapisearchjson.php +++ b/actions/twitapisearchjson.php @@ -134,9 +134,9 @@ class TwitapisearchjsonAction extends ApiAction $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/lib/api.php b/lib/api.php index 95a0779add..0801d28239 100644 --- a/lib/api.php +++ b/lib/api.php @@ -106,7 +106,7 @@ class ApiAction extends Action return parent::element($tag, $attrs, $content); } - function twitter_user_array($profile, $get_notice=false) + function twitterUserArray($profile, $get_notice=false) { $twitter_user = array(); @@ -133,7 +133,7 @@ class ApiAction extends Action $twitter_user['friends_count'] = $profile->subscriptionCount(); - $twitter_user['created_at'] = $this->date_twitter($profile->created); + $twitter_user['created_at'] = $this->dateTwitter($profile->created); $twitter_user['favourites_count'] = $profile->faveCount(); // British spelling! @@ -179,24 +179,24 @@ class ApiAction extends Action $notice = $profile->getCurrentNotice(); if ($notice) { # don't get user! - $twitter_user['status'] = $this->twitter_status_array($notice, false); + $twitter_user['status'] = $this->twitterStatusArray($notice, false); } } return $twitter_user; } - function twitter_status_array($notice, $include_user=true) + function twitterStatusArray($notice, $include_user=true) { $profile = $notice->getProfile(); $twitter_status = array(); $twitter_status['text'] = $notice->content; $twitter_status['truncated'] = false; # Not possible on StatusNet - $twitter_status['created_at'] = $this->date_twitter($notice->created); + $twitter_status['created_at'] = $this->dateTwitter($notice->created); $twitter_status['in_reply_to_status_id'] = ($notice->reply_to) ? intval($notice->reply_to) : null; - $twitter_status['source'] = $this->source_link($notice->source); + $twitter_status['source'] = $this->sourceLink($notice->source); $twitter_status['id'] = intval($notice->id); $replier_profile = null; @@ -239,14 +239,14 @@ class ApiAction extends Action if ($include_user) { # Don't get notice (recursive!) - $twitter_user = $this->twitter_user_array($profile, false); + $twitter_user = $this->twitterUserArray($profile, false); $twitter_status['user'] = $twitter_user; } return $twitter_status; } - function twitter_group_array($group) + function twitterGroupArray($group) { $twitter_group=array(); $twitter_group['id']=$group->id; @@ -261,12 +261,12 @@ class ApiAction extends Action $twitter_group['homepage']=$group->homepage; $twitter_group['description']=$group->description; $twitter_group['location']=$group->location; - $twitter_group['created']=$this->date_twitter($group->created); - $twitter_group['modified']=$this->date_twitter($group->modified); + $twitter_group['created']=$this->dateTwitter($group->created); + $twitter_group['modified']=$this->dateTwitter($group->modified); return $twitter_group; } - function twitter_rss_group_array($group) + function twitterRssGroupArray($group) { $entry = array(); $entry['content']=$group->description; @@ -284,7 +284,7 @@ class ApiAction extends Action return $entry; } - function twitter_rss_entry_array($notice) + function twitterRssEntryArray($notice) { $profile = $notice->getProfile(); $entry = array(); @@ -341,19 +341,19 @@ class ApiAction extends Action } - function twitter_relationship_array($source, $target) + function twitterRelationshipArray($source, $target) { $relationship = array(); $relationship['source'] = - $this->relationship_details_array($source, $target); + $this->relationshipDetailsArray($source, $target); $relationship['target'] = - $this->relationship_details_array($target, $source); + $this->relationshipDetailsArray($target, $source); return array('relationship' => $relationship); } - function relationship_details_array($source, $target) + function relationshipDetailsArray($source, $target) { $details = array(); @@ -380,14 +380,14 @@ class ApiAction extends Action return $details; } - function show_twitter_xml_relationship($relationship) + function showTwitterXmlRelationship($relationship) { $this->elementStart('relationship'); foreach($relationship as $element => $value) { if ($element == 'source' || $element == 'target') { $this->elementStart($element); - $this->show_xml_relationship_details($value); + $this->showXmlRelationshipDetails($value); $this->elementEnd($element); } } @@ -395,26 +395,26 @@ class ApiAction extends Action $this->elementEnd('relationship'); } - function show_xml_relationship_details($details) + function showXmlRelationshipDetails($details) { foreach($details as $element => $value) { $this->element($element, null, $value); } } - function show_twitter_xml_status($twitter_status) + function showTwitterXmlStatus($twitter_status) { $this->elementStart('status'); foreach($twitter_status as $element => $value) { switch ($element) { case 'user': - $this->show_twitter_xml_user($twitter_status['user']); + $this->showTwitterXmlUser($twitter_status['user']); break; case 'text': $this->element($element, null, common_xml_safe_str($value)); break; case 'attachments': - $this->show_xml_attachments($twitter_status['attachments']); + $this->showXmlAttachments($twitter_status['attachments']); break; default: $this->element($element, null, $value); @@ -423,7 +423,7 @@ class ApiAction extends Action $this->elementEnd('status'); } - function show_twitter_xml_group($twitter_group) + function showTwitterXmlGroup($twitter_group) { $this->elementStart('group'); foreach($twitter_group as $element => $value) { @@ -432,12 +432,12 @@ class ApiAction extends Action $this->elementEnd('group'); } - function show_twitter_xml_user($twitter_user, $role='user') + function showTwitterXmlUser($twitter_user, $role='user') { $this->elementStart($role); foreach($twitter_user as $element => $value) { if ($element == 'status') { - $this->show_twitter_xml_status($twitter_user['status']); + $this->showTwitterXmlStatus($twitter_user['status']); } else { $this->element($element, null, $value); } @@ -445,7 +445,7 @@ class ApiAction extends Action $this->elementEnd($role); } - function show_xml_attachments($attachments) { + function showXmlAttachments($attachments) { if (!empty($attachments)) { $this->elementStart('attachments', array('type' => 'array')); foreach ($attachments as $attachment) { @@ -459,7 +459,7 @@ class ApiAction extends Action } } - function show_twitter_rss_item($entry) + function showTwitterRssItem($entry) { $this->elementStart('item'); $this->element('title', null, $entry['title']); @@ -483,59 +483,59 @@ class ApiAction extends Action $this->elementEnd('item'); } - function show_json_objects($objects) + function showJsonObjects($objects) { print(json_encode($objects)); } - function show_single_xml_status($notice) + function showSingleXmlStatus($notice) { - $this->init_document('xml'); - $twitter_status = $this->twitter_status_array($notice); - $this->show_twitter_xml_status($twitter_status); - $this->end_document('xml'); + $this->initDocument('xml'); + $twitter_status = $this->twitterStatusArray($notice); + $this->showTwitterXmlStatus($twitter_status); + $this->endDocument('xml'); } function show_single_json_status($notice) { - $this->init_document('json'); - $status = $this->twitter_status_array($notice); - $this->show_json_objects($status); - $this->end_document('json'); + $this->initDocument('json'); + $status = $this->twitterStatusArray($notice); + $this->showJsonObjects($status); + $this->endDocument('json'); } - function show_xml_timeline($notice) + function showXmlTimeline($notice) { - $this->init_document('xml'); + $this->initDocument('xml'); $this->elementStart('statuses', array('type' => 'array')); if (is_array($notice)) { foreach ($notice as $n) { - $twitter_status = $this->twitter_status_array($n); - $this->show_twitter_xml_status($twitter_status); + $twitter_status = $this->twitterStatusArray($n); + $this->showTwitterXmlStatus($twitter_status); } } else { while ($notice->fetch()) { - $twitter_status = $this->twitter_status_array($notice); - $this->show_twitter_xml_status($twitter_status); + $twitter_status = $this->twitterStatusArray($notice); + $this->showTwitterXmlStatus($twitter_status); } } $this->elementEnd('statuses'); - $this->end_document('xml'); + $this->endDocument('xml'); } - function show_rss_timeline($notice, $title, $link, $subtitle, $suplink=null) + function showRssTimeline($notice, $title, $link, $subtitle, $suplink=null) { - $this->init_document('rss'); + $this->initDocument('rss'); $this->element('title', null, $title); $this->element('link', null, $link); if (!is_null($suplink)) { - # For FriendFeed's SUP protocol + // For FriendFeed's SUP protocol $this->element('link', array('xmlns' => 'http://www.w3.org/2005/Atom', 'rel' => 'http://api.friendfeed.com/2008/03#sup', 'href' => $suplink, @@ -547,23 +547,23 @@ class ApiAction extends Action if (is_array($notice)) { foreach ($notice as $n) { - $entry = $this->twitter_rss_entry_array($n); - $this->show_twitter_rss_item($entry); + $entry = $this->twitterRssEntryArray($n); + $this->showTwitterRssItem($entry); } } else { while ($notice->fetch()) { - $entry = $this->twitter_rss_entry_array($notice); - $this->show_twitter_rss_item($entry); + $entry = $this->twitterRssEntryArray($notice); + $this->showTwitterRssItem($entry); } } - $this->end_twitter_rss(); + $this->endTwitterRss(); } - function show_atom_timeline($notice, $title, $id, $link, $subtitle=null, $suplink=null, $selfuri=null) + function showAtomTimeline($notice, $title, $id, $link, $subtitle=null, $suplink=null, $selfuri=null) { - $this->init_document('atom'); + $this->initDocument('atom'); $this->element('title', null, $title); $this->element('id', null, $id); @@ -594,14 +594,14 @@ class ApiAction extends Action } } - $this->end_document('atom'); + $this->endDocument('atom'); } - function show_rss_groups($group, $title, $link, $subtitle) + function showRssGroups($group, $title, $link, $subtitle) { - $this->init_document('rss'); + $this->initDocument('rss'); $this->element('title', null, $title); $this->element('link', null, $link); @@ -611,17 +611,17 @@ class ApiAction extends Action if (is_array($group)) { foreach ($group as $g) { - $twitter_group = $this->twitter_rss_group_array($g); - $this->show_twitter_rss_item($twitter_group); + $twitter_group = $this->twitterRssGroupArray($g); + $this->showTwitterRssItem($twitter_group); } } else { while ($group->fetch()) { - $twitter_group = $this->twitter_rss_group_array($group); - $this->show_twitter_rss_item($twitter_group); + $twitter_group = $this->twitterRssGroupArray($group); + $this->showTwitterRssItem($twitter_group); } } - $this->end_twitter_rss(); + $this->endTwitterRss(); } @@ -655,7 +655,7 @@ class ApiAction extends Action switch ($element) { case 'sender': case 'recipient': - $this->show_twitter_xml_user($value, $element); + $this->showTwitterXmlUser($value, $element); break; case 'text': $this->element($element, null, common_xml_safe_str($value)); @@ -679,11 +679,11 @@ class ApiAction extends Action $dmsg['sender_id'] = $message->from_profile; $dmsg['text'] = trim($message->content); $dmsg['recipient_id'] = $message->to_profile; - $dmsg['created_at'] = $this->date_twitter($message->created); + $dmsg['created_at'] = $this->dateTwitter($message->created); $dmsg['sender_screen_name'] = $from_profile->nickname; $dmsg['recipient_screen_name'] = $to_profile->nickname; - $dmsg['sender'] = $this->twitter_user_array($from_profile, false); - $dmsg['recipient'] = $this->twitter_user_array($to_profile, false); + $dmsg['sender'] = $this->twitterUserArray($from_profile, false); + $dmsg['recipient'] = $this->twitterUserArray($to_profile, false); return $dmsg; } @@ -725,24 +725,24 @@ class ApiAction extends Action function showSingleXmlDirectMessage($message) { - $this->init_document('xml'); + $this->initDocument('xml'); $dmsg = $this->directMessageArray($message); $this->showXmlDirectMessage($dmsg); - $this->end_document('xml'); + $this->endDocument('xml'); } function showSingleJsonDirectMessage($message) { - $this->init_document('json'); + $this->initDocument('json'); $dmsg = $this->directMessageArray($message); - $this->show_json_objects($dmsg); - $this->end_document('json'); + $this->showJsonObjects($dmsg); + $this->endDocument('json'); } - function show_atom_groups($group, $title, $id, $link, $subtitle=null, $selfuri=null) + function showAtomGroups($group, $title, $id, $link, $subtitle=null, $selfuri=null) { - $this->init_document('atom'); + $this->initDocument('atom'); $this->element('title', null, $title); $this->element('id', null, $id); @@ -766,143 +766,143 @@ class ApiAction extends Action } } - $this->end_document('atom'); + $this->endDocument('atom'); } - function show_json_timeline($notice) + function showJsonTimeline($notice) { - $this->init_document('json'); + $this->initDocument('json'); $statuses = array(); if (is_array($notice)) { foreach ($notice as $n) { - $twitter_status = $this->twitter_status_array($n); + $twitter_status = $this->twitterStatusArray($n); array_push($statuses, $twitter_status); } } else { while ($notice->fetch()) { - $twitter_status = $this->twitter_status_array($notice); + $twitter_status = $this->twitterStatusArray($notice); array_push($statuses, $twitter_status); } } - $this->show_json_objects($statuses); + $this->showJsonObjects($statuses); - $this->end_document('json'); + $this->endDocument('json'); } - function show_json_groups($group) + function showJsonGroups($group) { - $this->init_document('json'); + $this->initDocument('json'); $groups = array(); if (is_array($group)) { foreach ($group as $g) { - $twitter_group = $this->twitter_group_array($g); + $twitter_group = $this->twitterGroupArray($g); array_push($groups, $twitter_group); } } else { while ($group->fetch()) { - $twitter_group = $this->twitter_group_array($group); + $twitter_group = $this->twitterGroupArray($group); array_push($groups, $twitter_group); } } - $this->show_json_objects($groups); + $this->showJsonObjects($groups); - $this->end_document('json'); + $this->endDocument('json'); } - function show_xml_groups($group) + function showXmlGroups($group) { - $this->init_document('xml'); + $this->initDocument('xml'); $this->elementStart('groups', array('type' => 'array')); if (is_array($group)) { foreach ($group as $g) { - $twitter_group = $this->twitter_group_array($g); - $this->show_twitter_xml_group($twitter_group); + $twitter_group = $this->twitterGroupArray($g); + $this->showTwitterXmlGroup($twitter_group); } } else { while ($group->fetch()) { - $twitter_group = $this->twitter_group_array($group); - $this->show_twitter_xml_group($twitter_group); + $twitter_group = $this->twitterGroupArray($group); + $this->showTwitterXmlGroup($twitter_group); } } $this->elementEnd('groups'); - $this->end_document('xml'); + $this->endDocument('xml'); } - function show_twitter_xml_users($user) + function showTwitterXmlUsers($user) { - $this->init_document('xml'); + $this->initDocument('xml'); $this->elementStart('users', array('type' => 'array')); if (is_array($user)) { foreach ($user as $u) { - $twitter_user = $this->twitter_user_array($u); - $this->show_twitter_xml_user($twitter_user); + $twitter_user = $this->twitterUserArray($u); + $this->showTwitterXmlUser($twitter_user); } } else { while ($user->fetch()) { - $twitter_user = $this->twitter_user_array($user); - $this->show_twitter_xml_user($twitter_user); + $twitter_user = $this->twitterUserArray($user); + $this->showTwitterXmlUser($twitter_user); } } $this->elementEnd('users'); - $this->end_document('xml'); + $this->endDocument('xml'); } - function show_json_users($user) + function showJsonUsers($user) { - $this->init_document('json'); + $this->initDocument('json'); $users = array(); if (is_array($user)) { foreach ($user as $u) { - $twitter_user = $this->twitter_user_array($u); + $twitter_user = $this->twitterUserArray($u); array_push($users, $twitter_user); } } else { while ($user->fetch()) { - $twitter_user = $this->twitter_user_array($user); + $twitter_user = $this->twitterUserArray($user); array_push($users, $twitter_user); } } - $this->show_json_objects($users); + $this->showJsonObjects($users); - $this->end_document('json'); + $this->endDocument('json'); } - function show_single_json_group($group) + function showSingleJsonGroup($group) { - $this->init_document('json'); - $twitter_group = $this->twitter_group_array($group); - $this->show_json_objects($twitter_group); - $this->end_document('json'); + $this->initDocument('json'); + $twitter_group = $this->twitterGroupArray($group); + $this->showJsonObjects($twitter_group); + $this->endDocument('json'); } function show_single_xml_group($group) { - $this->init_document('xml'); - $twitter_group = $this->twitter_group_array($group); - $this->show_twitter_xml_group($twitter_group); - $this->end_document('xml'); + $this->initDocument('xml'); + $twitter_group = $this->twitterGroupArray($group); + $this->showTwitterXmlGroup($twitter_group); + $this->endDocument('xml'); } - function date_twitter($dt) + function dateTwitter($dt) { $dateStr = date('d F Y H:i:s', strtotime($dt)); $d = new DateTime($dateStr, new DateTimeZone('UTC')); @@ -910,24 +910,7 @@ class ApiAction extends Action return $d->format('D M d H:i:s O Y'); } - // XXX: Candidate for a general utility method somewhere? - function count_subscriptions($profile) - { - - $count = 0; - $sub = new Subscription(); - $sub->subscribed = $profile->id; - - $count = $sub->find(); - - if ($count > 0) { - return $count - 1; - } else { - return 0; - } - } - - function init_document($type='xml') + function initDocument($type='xml') { switch ($type) { case 'xml': @@ -945,11 +928,11 @@ class ApiAction extends Action break; case 'rss': header("Content-Type: application/rss+xml; charset=utf-8"); - $this->init_twitter_rss(); + $this->initTwitterRss(); break; case 'atom': header('Content-Type: application/atom+xml; charset=utf-8'); - $this->init_twitter_atom(); + $this->initTwitterAtom(); break; default: $this->clientError(_('Not a supported data format.')); @@ -959,7 +942,7 @@ class ApiAction extends Action return; } - function end_document($type='xml') + function endDocument($type='xml') { switch ($type) { case 'xml': @@ -974,10 +957,10 @@ class ApiAction extends Action } break; case 'rss': - $this->end_twitter_rss(); + $this->endTwitterRss(); break; case 'atom': - $this->end_twitter_rss(); + $this->endTwitterRss(); break; default: $this->clientError(_('Not a supported data format.')); @@ -1001,17 +984,17 @@ class ApiAction extends Action header('HTTP/1.1 '.$code.' '.$status_string); if ($format == 'xml') { - $this->init_document('xml'); + $this->initDocument('xml'); $this->elementStart('hash'); $this->element('error', null, $msg); $this->element('request', null, $_SERVER['REQUEST_URI']); $this->elementEnd('hash'); - $this->end_document('xml'); + $this->endDocument('xml'); } elseif ($format == 'json'){ - $this->init_document('json'); + $this->initDocument('json'); $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); print(json_encode($error_array)); - $this->end_document('json'); + $this->endDocument('json'); } else { // If user didn't request a useful format, throw a regular client error @@ -1034,21 +1017,21 @@ class ApiAction extends Action header('HTTP/1.1 '.$code.' '.$status_string); if ($content_type == 'xml') { - $this->init_document('xml'); + $this->initDocument('xml'); $this->elementStart('hash'); $this->element('error', null, $msg); $this->element('request', null, $_SERVER['REQUEST_URI']); $this->elementEnd('hash'); - $this->end_document('xml'); + $this->endDocument('xml'); } else { - $this->init_document('json'); + $this->initDocument('json'); $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); print(json_encode($error_array)); - $this->end_document('json'); + $this->endDocument('json'); } } - function init_twitter_rss() + function initTwitterRss() { $this->startXML(); $this->elementStart('rss', array('version' => '2.0', 'xmlns:atom'=>'http://www.w3.org/2005/Atom')); @@ -1056,14 +1039,14 @@ class ApiAction extends Action Event::handle('StartApiRss', array($this)); } - function end_twitter_rss() + function endTwitterRss() { $this->elementEnd('channel'); $this->elementEnd('rss'); $this->endXML(); } - function init_twitter_atom() + function initTwitterAtom() { $this->startXML(); // FIXME: don't hardcode the language here! @@ -1073,21 +1056,21 @@ class ApiAction extends Action Event::handle('StartApiAtom', array($this)); } - function end_twitter_atom() + function endTwitterAtom() { $this->elementEnd('feed'); $this->endXML(); } - function show_profile($profile, $content_type='xml', $notice=null, $includeStatuses=true) + function showProfile($profile, $content_type='xml', $notice=null, $includeStatuses=true) { - $profile_array = $this->twitter_user_array($profile, $includeStatuses); + $profile_array = $this->twitterUserArray($profile, $includeStatuses); switch ($content_type) { case 'xml': - $this->show_twitter_xml_user($profile_array); + $this->showTwitterXmlUser($profile_array); break; case 'json': - $this->show_json_objects($profile_array); + $this->showJsonObjects($profile_array); break; default: $this->clientError(_('Not a supported data format.')); @@ -1155,7 +1138,7 @@ class ApiAction extends Action } } - function source_link($source) + function sourceLink($source) { $source_name = _($source); switch ($source) { diff --git a/lib/twitter.php b/lib/twitter.php index b49e2e1190..afc3f55bab 100644 --- a/lib/twitter.php +++ b/lib/twitter.php @@ -23,7 +23,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { define('TWITTER_SERVICE', 1); // Twitter is foreign_service ID 1 -function update_twitter_user($twitter_id, $screen_name) +function updateTwitter_user($twitter_id, $screen_name) { $uri = 'http://twitter.com/' . $screen_name; $fuser = new Foreign_user(); @@ -115,7 +115,7 @@ function save_twitter_user($twitter_id, $screen_name) // Only update if Twitter screen name has changed if ($fuser->nickname != $screen_name) { - $result = update_twitter_user($twitter_id, $screen_name); + $result = updateTwitter_user($twitter_id, $screen_name); common_debug('Twitter bridge - Updated nickname (and URI) for Twitter user ' . "$fuser->id to $screen_name, was $fuser->nickname"); diff --git a/plugins/Realtime/RealtimePlugin.php b/plugins/Realtime/RealtimePlugin.php index 9a750bbc8d..0c7c1240c3 100644 --- a/plugins/Realtime/RealtimePlugin.php +++ b/plugins/Realtime/RealtimePlugin.php @@ -246,7 +246,7 @@ class RealtimePlugin extends Plugin $act = new ApiAction('/dev/null'); - $arr = $act->twitter_status_array($notice, true); + $arr = $act->twitterStatusArray($notice, true); $arr['url'] = $notice->bestUrl(); $arr['html'] = htmlspecialchars($notice->rendered); $arr['source'] = htmlspecialchars($arr['source']); From 7fcaffdf86755a444ad9c24046161cb8a428c613 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 12 Oct 2009 14:07:00 -0700 Subject: [PATCH 44/49] Took out some unnecessary intializations --- actions/apifavoritecreate.php | 2 -- actions/apifavoritedestroy.php | 1 - actions/apifriendshipscreate.php | 1 - actions/apifriendshipsdestroy.php | 1 - actions/apifriendshipsshow.php | 1 - actions/apiusershow.php | 2 -- 6 files changed, 8 deletions(-) diff --git a/actions/apifavoritecreate.php b/actions/apifavoritecreate.php index 1b05eb95c9..2a185f6073 100644 --- a/actions/apifavoritecreate.php +++ b/actions/apifavoritecreate.php @@ -46,7 +46,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiFavoriteCreateAction extends ApiAuthAction { - var $user = null; var $notice = null; /** @@ -141,7 +140,6 @@ class ApiFavoriteCreateAction extends ApiAuthAction } } - /** * Notify the author of the favorite that the user likes their notice * diff --git a/actions/apifavoritedestroy.php b/actions/apifavoritedestroy.php index aac866d7e9..f954a50760 100644 --- a/actions/apifavoritedestroy.php +++ b/actions/apifavoritedestroy.php @@ -47,7 +47,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiFavoriteDestroyAction extends ApiAuthAction { - var $user = null; var $notice = null; /** diff --git a/actions/apifriendshipscreate.php b/actions/apifriendshipscreate.php index 6c44d79610..fe4e9e9a2b 100644 --- a/actions/apifriendshipscreate.php +++ b/actions/apifriendshipscreate.php @@ -47,7 +47,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiFriendshipsCreateAction extends ApiAuthAction { - var $user = null; var $other = null; /** diff --git a/actions/apifriendshipsdestroy.php b/actions/apifriendshipsdestroy.php index a15f202aa8..f0f6c062b5 100644 --- a/actions/apifriendshipsdestroy.php +++ b/actions/apifriendshipsdestroy.php @@ -47,7 +47,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiFriendshipsDestroyAction extends ApiAuthAction { - var $user = null; var $other = null; /** diff --git a/actions/apifriendshipsshow.php b/actions/apifriendshipsshow.php index 8850496c79..c5aed238f4 100644 --- a/actions/apifriendshipsshow.php +++ b/actions/apifriendshipsshow.php @@ -45,7 +45,6 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; class ApiFriendshipsShowAction extends ApiBareAuthAction { - var $user = null; var $source = null; var $target = null; diff --git a/actions/apiusershow.php b/actions/apiusershow.php index d07040a43d..db942d1a58 100644 --- a/actions/apiusershow.php +++ b/actions/apiusershow.php @@ -46,8 +46,6 @@ require_once INSTALLDIR.'/lib/api.php'; class ApiUserShowAction extends ApiAction { - var $user = null; - /** * Take arguments for running * From da9d02b0381e1acb2a5250392d91b0ebe6e87c1b Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 12 Oct 2009 14:46:22 -0700 Subject: [PATCH 45/49] Make apigroupcreate.php pass phpcs --- actions/apigroupcreate.php | 130 +++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 57 deletions(-) diff --git a/actions/apigroupcreate.php b/actions/apigroupcreate.php index d6340eebfc..aeae1c2b2c 100644 --- a/actions/apigroupcreate.php +++ b/actions/apigroupcreate.php @@ -94,22 +94,22 @@ class ApiGroupCreateAction extends ApiAuthAction { 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.'), + if (!common_config('inboxes', 'enabled')) { + $this->serverError( + _('Inboxes must be enabled for groups to work'), 400, $this->format ); - return; + return false; + } + + if ($_SERVER['REQUEST_METHOD'] != 'POST') { + $this->clientError( + _('This method requires a POST.'), + 400, + $this->format + ); + return; } if (empty($this->user)) { @@ -202,14 +202,15 @@ class ApiGroupCreateAction extends ApiAuthAction function validateParams() { - if (!Validate::string( + $valid = Validate::string( $this->nickname, array( 'min_length' => 1, 'max_length' => 64, - 'format' => NICKNAME_FMT) - ) + 'format' => NICKNAME_FMT ) - { + ); + + if (!$valid) { $this->clientError( _( 'Nickname must have only lowercase letters ' . @@ -234,24 +235,24 @@ class ApiGroupCreateAction extends ApiAuthAction ); return false; - } elseif (!is_null($this->homepage) + } 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) - { + } elseif ( + !is_null($this->fullname) + && mb_strlen($this->fullname) > 255) { $this->clientError( _('Full name is too long (max 255 chars).'), 403, @@ -259,16 +260,18 @@ class ApiGroupCreateAction extends ApiAuthAction ); return false; } elseif (User_group::descriptionTooLong($this->description)) { - $this->clientError(sprintf( - _('Description is too long (max %d chars).'), - User_group::maxDescription()), - 403, - $this->format - ); + $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) - { + } elseif ( + !is_null($this->location) + && mb_strlen($this->location) > 255) { $this->clientError( _('Location is too long (max 255 chars).'), 403, @@ -280,9 +283,7 @@ class ApiGroupCreateAction extends ApiAuthAction if (!empty($this->aliasstring)) { $this->aliases = array_map( 'common_canonical_nickname', - array_unique(preg_split('/[\s,]+/', - $this->aliasstring) - ) + array_unique(preg_split('/[\s,]+/', $this->aliasstring)) ); } else { $this->aliases = array(); @@ -290,22 +291,27 @@ class ApiGroupCreateAction extends ApiAuthAction if (count($this->aliases) > common_config('group', 'maxaliases')) { $this->clientError( - sprintf(_('Too many aliases! Maximum %d.'), - common_config('group', 'maxaliases')), - 403, - $this->format - ); + sprintf( + _('Too many aliases! Maximum %d.'), + common_config('group', 'maxaliases') + ), + 403, + $this->format + ); return false; } foreach ($this->aliases as $alias) { - if (!Validate::string($alias, array( - 'min_length' => 1, - 'max_length' => 64, - 'format' => NICKNAME_FMT + + $valid = Validate::string( + $alias, array( + 'min_length' => 1, + 'max_length' => 64, + 'format' => NICKNAME_FMT ) - )) - { + ); + + if (!$valid) { $this->clientError( sprintf(_('Invalid alias: "%s"'), $alias), 403, @@ -315,8 +321,10 @@ class ApiGroupCreateAction extends ApiAuthAction } if ($this->groupNicknameExists($alias)) { $this->clientError( - sprintf(_('Alias "%s" already in use. Try another one.'), - $alias), + sprintf( + _('Alias "%s" already in use. Try another one.'), + $alias + ), 403, $this->format ); @@ -340,21 +348,29 @@ class ApiGroupCreateAction extends ApiAuthAction 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); + $group = User_group::staticGet('nickname', $nickname); - if (!empty($group)) { - return true; - } + if (!empty($group)) { + return true; + } - $alias = Group_alias::staticGet('alias', $nickname); + $alias = Group_alias::staticGet('alias', $nickname); - if (!empty($alias)) { - return true; - } + if (!empty($alias)) { + return true; + } - return false; + return false; } } From 4efbe32f6ae2d0300299b1103294f881a03f929d Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 12 Oct 2009 15:12:20 -0700 Subject: [PATCH 46/49] Use site's name for basic auth realm --- lib/apiauth.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/apiauth.php b/lib/apiauth.php index 25bbae24e5..4e5e0ccd99 100644 --- a/lib/apiauth.php +++ b/lib/apiauth.php @@ -31,7 +31,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/api.php'; +require_once INSTALLDIR . '/lib/api.php'; /** * Actions extending this class will require auth @@ -90,8 +90,10 @@ class ApiAuthAction extends ApiAction { $this->basicAuthProcessHeader(); + $realm = common_config('site', 'name') . ' API'; + if (!isset($this->auth_user)) { - header('WWW-Authenticate: Basic realm="StatusNet API"'); + header('WWW-Authenticate: Basic realm="' . $realm . '"'); // show error if the user clicks 'cancel' From 870b091693531ba9aca20a0b0fa64ec326d72725 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 12 Oct 2009 16:36:00 -0700 Subject: [PATCH 47/49] Added in credits. --- actions/apiaccountratelimitstatus.php | 8 ++++++-- actions/apiaccountverifycredentials.php | 6 +++++- actions/apiblockcreate.php | 15 ++++++++------- actions/apiblockdestroy.php | 3 ++- actions/apidirectmessage.php | 8 +++++++- actions/apidirectmessagenew.php | 11 ++++++++--- actions/apifavoritecreate.php | 6 +++++- actions/apifavoritedestroy.php | 6 +++++- actions/apifriendshipscreate.php | 6 +++++- actions/apifriendshipsdestroy.php | 6 +++++- actions/apifriendshipsexists.php | 8 ++++++-- actions/apifriendshipsshow.php | 18 +++++++++++------- actions/apigroupcreate.php | 5 +++++ actions/apigroupismember.php | 7 ++++++- actions/apigroupjoin.php | 7 ++++++- actions/apigroupleave.php | 11 ++++++++--- actions/apigrouplist.php | 8 +++++++- actions/apigrouplistall.php | 6 ++++++ actions/apigroupmembership.php | 18 ++++++++++++------ actions/apigroupshow.php | 8 +++++++- actions/apihelptest.php | 2 ++ actions/apistatusesdestroy.php | 16 +++++++++++++--- actions/apistatusesshow.php | 14 +++++++++++++- actions/apistatusesupdate.php | 16 +++++++++++++--- actions/apistatusnetconfig.php | 2 ++ actions/apistatusnetversion.php | 6 ++++-- actions/apisubscriptions.php | 6 +++++- actions/apitimelinefavorites.php | 7 +++++-- actions/apitimelinefriends.php | 14 +++++++++++++- actions/apitimelinegroup.php | 6 ++++++ actions/apitimelinementions.php | 15 +++++++++++++-- actions/apitimelinepublic.php | 14 +++++++++++++- actions/apitimelinetag.php | 8 +++++++- actions/apitimelineuser.php | 15 +++++++++++++-- actions/apiuserfollowers.php | 6 +++++- actions/apiuserfriends.php | 6 +++++- actions/apiusershow.php | 8 +++++++- lib/api.php | 10 ++++++++++ lib/apiauth.php | 9 ++++++++- lib/apibareauth.php | 16 +++++++++++++++- lib/twitterbasicauthclient.php | 10 ++++++++-- 41 files changed, 310 insertions(+), 67 deletions(-) diff --git a/actions/apiaccountratelimitstatus.php b/actions/apiaccountratelimitstatus.php index af86dae6a9..96179f175b 100644 --- a/actions/apiaccountratelimitstatus.php +++ b/actions/apiaccountratelimitstatus.php @@ -21,6 +21,8 @@ * * @category API * @package StatusNet + * @author Evan Prodromou + * @author Robin Millette * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,14 +33,16 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apibareauth.php'; +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: 100 hits left. + * It always returns the same thing: 150 hits left. * * @category API * @package StatusNet + * @author Evan Prodromou + * @author Robin Millette * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apiaccountverifycredentials.php b/actions/apiaccountverifycredentials.php index 8b976bbf3d..08b201dbff 100644 --- a/actions/apiaccountverifycredentials.php +++ b/actions/apiaccountverifycredentials.php @@ -21,6 +21,8 @@ * * @category API * @package StatusNet + * @author Evan Prodromou + * @author Robin Millette * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,7 +33,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/apiauth.php'; /** * Check a user's credentials. Returns an HTTP 200 OK response code and a @@ -40,6 +42,8 @@ require_once INSTALLDIR.'/lib/apiauth.php'; * * @category API * @package StatusNet + * @author Evan Prodromou + * @author Robin Millette * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apiblockcreate.php b/actions/apiblockcreate.php index e003e5ee96..1cab2df5d0 100644 --- a/actions/apiblockcreate.php +++ b/actions/apiblockcreate.php @@ -21,6 +21,7 @@ * * @category API * @package StatusNet + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -34,12 +35,13 @@ if (!defined('STATUSNET')) { 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 + * 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 * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -47,7 +49,6 @@ require_once INSTALLDIR . '/lib/apiauth.php'; class ApiBlockCreateAction extends ApiAuthAction { - var $user = null; var $other = null; /** @@ -91,13 +92,13 @@ class ApiBlockCreateAction extends ApiAuthAction ); return; } - + if (empty($this->user) || empty($this->other)) { $this->clientError(_('No such user!'), 404, $this->format); return; } - - if ($this->user->hasBlocked($this->other) + + if ($this->user->hasBlocked($this->other) || $this->user->block($this->other) ) { $this->initDocument($this->format); @@ -106,7 +107,7 @@ class ApiBlockCreateAction extends ApiAuthAction } else { $this->serverError(_('Block user failed.'), 500, $this->format); } - + } } diff --git a/actions/apiblockdestroy.php b/actions/apiblockdestroy.php index 470b60ea53..16dbf94caf 100644 --- a/actions/apiblockdestroy.php +++ b/actions/apiblockdestroy.php @@ -21,6 +21,7 @@ * * @category API * @package StatusNet + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -39,6 +40,7 @@ require_once INSTALLDIR . '/lib/apiauth.php'; * * @category API * @package StatusNet + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -46,7 +48,6 @@ require_once INSTALLDIR . '/lib/apiauth.php'; class ApiBlockDestroyAction extends ApiAuthAction { - var $user = null; var $other = null; /** diff --git a/actions/apidirectmessage.php b/actions/apidirectmessage.php index 4e55886d95..a21fe86d20 100644 --- a/actions/apidirectmessage.php +++ b/actions/apidirectmessage.php @@ -21,6 +21,9 @@ * * @category API * @package StatusNet + * @author Adrian Lang + * @author Evan Prodromou + * @author Robin Millette * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,13 +34,16 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apiauth.php'; +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 + * @author Evan Prodromou + * @author Robin Millette * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apidirectmessagenew.php b/actions/apidirectmessagenew.php index 6984c8d103..fa6cafbe8d 100644 --- a/actions/apidirectmessagenew.php +++ b/actions/apidirectmessagenew.php @@ -21,6 +21,9 @@ * * @category API * @package StatusNet + * @author Adrian Lang + * @author Evan Prodromou + * @author Robin Millette * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,7 +34,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/apiauth.php'; /** * Creates a new direct message from the authenticating user to @@ -39,6 +42,9 @@ require_once INSTALLDIR.'/lib/apiauth.php'; * * @category API * @package StatusNet + * @author Adrian Lang + * @author Evan Prodromou + * @author Robin Millette * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -47,7 +53,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiDirectMessageNewAction extends ApiAuthAction { var $source = null; - var $user = null; var $other = null; var $content = null; @@ -151,7 +156,7 @@ class ApiDirectMessageNewAction extends ApiAuthAction // Note: sending msgs to yourself is allowed by Twitter - $errmsg = 'Don\'t send a message to yourself; ' . + $errmsg = 'Don\'t send a message to yourself; ' . 'just say it to yourself quietly instead.' $this->clientError(_($errmsg), 403, $this->format); diff --git a/actions/apifavoritecreate.php b/actions/apifavoritecreate.php index 2a185f6073..a80a6492e9 100644 --- a/actions/apifavoritecreate.php +++ b/actions/apifavoritecreate.php @@ -21,6 +21,8 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,7 +33,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/apiauth.php'; /** * Favorites the status specified in the ID parameter as the authenticating user. @@ -39,6 +41,8 @@ require_once INSTALLDIR.'/lib/apiauth.php'; * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apifavoritedestroy.php b/actions/apifavoritedestroy.php index f954a50760..f131d1c7f2 100644 --- a/actions/apifavoritedestroy.php +++ b/actions/apifavoritedestroy.php @@ -21,6 +21,8 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,7 +33,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/apiauth.php'; /** * Un-favorites the status specified in the ID parameter as the authenticating user. @@ -39,6 +41,8 @@ require_once INSTALLDIR.'/lib/apiauth.php'; * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apifriendshipscreate.php b/actions/apifriendshipscreate.php index fe4e9e9a2b..a824e734bf 100644 --- a/actions/apifriendshipscreate.php +++ b/actions/apifriendshipscreate.php @@ -21,6 +21,8 @@ * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,7 +33,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/apiauth.php'; /** * Allows the authenticating users to follow (subscribe) the user specified in @@ -40,6 +42,8 @@ require_once INSTALLDIR.'/lib/apiauth.php'; * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apifriendshipsdestroy.php b/actions/apifriendshipsdestroy.php index f0f6c062b5..3d9b7e001c 100644 --- a/actions/apifriendshipsdestroy.php +++ b/actions/apifriendshipsdestroy.php @@ -21,6 +21,8 @@ * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,7 +33,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/apiauth.php'; /** * Allows the authenticating users to unfollow (unsubscribe) the user specified in @@ -40,6 +42,8 @@ require_once INSTALLDIR.'/lib/apiauth.php'; * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apifriendshipsexists.php b/actions/apifriendshipsexists.php index 93be5f84ea..ae50c512c8 100644 --- a/actions/apifriendshipsexists.php +++ b/actions/apifriendshipsexists.php @@ -21,6 +21,8 @@ * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,14 +33,16 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/api.php'; +require_once INSTALLDIR . '/lib/api.php'; /** - * Tests for the existence of friendship between two users. Will return true if + * 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 + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apifriendshipsshow.php b/actions/apifriendshipsshow.php index c5aed238f4..8fc4367388 100644 --- a/actions/apifriendshipsshow.php +++ b/actions/apifriendshipsshow.php @@ -21,6 +21,8 @@ * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,13 +33,15 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apibareauth.php'; +require_once INSTALLDIR . '/lib/apibareauth.php'; /** * Outputs detailed information about the relationship between two users * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -65,7 +69,7 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction $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)) { @@ -90,7 +94,7 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction * * @return boolean true or false */ - + function requiresAuth() { if (common_config('site', 'private')) { @@ -125,7 +129,7 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction $this->clientError(_('API method not found!'), 404); return; } - + if (empty($this->source)) { $this->clientError( _('Could not determine source user.'), @@ -133,7 +137,7 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction ); return; } - + if (empty($this->target)) { $this->clientError( _('Could not find target user.'), @@ -141,7 +145,7 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction ); return; } - + $result = $this->twitterRelationshipArray($this->source, $this->target); switch ($this->format) { @@ -158,7 +162,7 @@ class ApiFriendshipsShowAction extends ApiBareAuthAction default: break; } - + } } diff --git a/actions/apigroupcreate.php b/actions/apigroupcreate.php index aeae1c2b2c..cdb2afb5be 100644 --- a/actions/apigroupcreate.php +++ b/actions/apigroupcreate.php @@ -22,6 +22,8 @@ * @category API * @package StatusNet * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -39,6 +41,9 @@ require_once INSTALLDIR . '/lib/apiauth.php'; * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apigroupismember.php b/actions/apigroupismember.php index 6cf3270129..a8a40a6b3b 100644 --- a/actions/apigroupismember.php +++ b/actions/apigroupismember.php @@ -21,6 +21,9 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -38,6 +41,9 @@ require_once INSTALLDIR . '/lib/apibareauth.php'; * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -45,7 +51,6 @@ require_once INSTALLDIR . '/lib/apibareauth.php'; class ApiGroupIsMemberAction extends ApiBareAuthAction { - var $user = null; var $group = null; /** diff --git a/actions/apigroupjoin.php b/actions/apigroupjoin.php index f930aa5190..071cd9290f 100644 --- a/actions/apigroupjoin.php +++ b/actions/apigroupjoin.php @@ -21,6 +21,9 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -38,6 +41,9 @@ require_once INSTALLDIR . '/lib/apiauth.php'; * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -45,7 +51,6 @@ require_once INSTALLDIR . '/lib/apiauth.php'; class ApiGroupJoinAction extends ApiAuthAction { - var $user = null; var $group = null; /** diff --git a/actions/apigroupleave.php b/actions/apigroupleave.php index 4e3192ac08..0d4bb9e4d3 100644 --- a/actions/apigroupleave.php +++ b/actions/apigroupleave.php @@ -21,6 +21,9 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -38,6 +41,9 @@ require_once INSTALLDIR . '/lib/apiauth.php'; * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -45,7 +51,6 @@ require_once INSTALLDIR . '/lib/apiauth.php'; class ApiGroupLeaveAction extends ApiAuthAction { - var $user = null; var $group = null; /** @@ -117,13 +122,13 @@ class ApiGroupLeaveAction extends ApiAuthAction $this->serverError( sprintf( _('Could not remove user %s to group %s.'), - $this->user->nickname, + $this->user->nickname, $this->$group->nickname ) ); return; } - + switch($this->format) { case 'xml': $this->show_single_xml_group($this->group); diff --git a/actions/apigrouplist.php b/actions/apigrouplist.php index 1fc31831a0..c529c1e408 100644 --- a/actions/apigrouplist.php +++ b/actions/apigrouplist.php @@ -21,6 +21,9 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -38,6 +41,9 @@ require_once INSTALLDIR . '/lib/apibareauth.php'; * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -59,7 +65,7 @@ class ApiGroupListAction extends ApiBareAuthAction function prepare($args) { parent::prepare($args); - + $this->user = $this->getTargetUser($id); $this->groups = $this->getGroups(); diff --git a/actions/apigrouplistall.php b/actions/apigrouplistall.php index ef96a08bdd..89469f36f4 100644 --- a/actions/apigrouplistall.php +++ b/actions/apigrouplistall.php @@ -21,6 +21,9 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -38,6 +41,9 @@ require_once INSTALLDIR . '/lib/api.php'; * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apigroupmembership.php b/actions/apigroupmembership.php index 27f77029eb..b31e47b398 100644 --- a/actions/apigroupmembership.php +++ b/actions/apigroupmembership.php @@ -21,6 +21,9 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -34,10 +37,13 @@ if (!defined('STATUSNET')) { require_once INSTALLDIR . '/lib/api.php'; /** - * List 20 newest members of the group specified by name or ID. + * List 20 newest members of the group specified by name or ID. * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -103,7 +109,7 @@ class ApiGroupMembershipAction extends ApiAction /** * Fetch the members of a group * - * @return array $profiles list of profiles + * @return array $profiles list of profiles */ function getProfiles() @@ -112,9 +118,9 @@ class ApiGroupMembershipAction extends ApiAction $profile = $this->group->getMembers( ($this->page - 1) * $this->count, - $this->count, - $this->since_id, - $this->max_id, + $this->count, + $this->since_id, + $this->max_id, $this->since ); @@ -157,7 +163,7 @@ class ApiGroupMembershipAction extends ApiAction * 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 + * the group id, and timestamps of the first and last * user who has joined the group * * @return string etag diff --git a/actions/apigroupshow.php b/actions/apigroupshow.php index 8969ae194b..2bdb22bc41 100644 --- a/actions/apigroupshow.php +++ b/actions/apigroupshow.php @@ -21,6 +21,9 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,13 +34,16 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/api.php'; +require_once INSTALLDIR . '/lib/api.php'; /** * Outputs detailed information about the group specified by ID * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apihelptest.php b/actions/apihelptest.php index 4691cbf99c..e4ef55f2e3 100644 --- a/actions/apihelptest.php +++ b/actions/apihelptest.php @@ -21,6 +21,7 @@ * * @category API * @package StatusNet + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -38,6 +39,7 @@ require_once INSTALLDIR . '/lib/api.php'; * * @category API * @package StatusNet + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apistatusesdestroy.php b/actions/apistatusesdestroy.php index 74a1310a22..8dc8793b53 100644 --- a/actions/apistatusesdestroy.php +++ b/actions/apistatusesdestroy.php @@ -21,6 +21,12 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author Tom Blankenship + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,13 +37,19 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/apiauth.php'; /** * Deletes one of the authenticating user's statuses (notices). * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author Tom Blankenship + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -45,8 +57,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiStatusesDestroyAction extends ApiAuthAction { - - var $user = null; var $status = null; /** diff --git a/actions/apistatusesshow.php b/actions/apistatusesshow.php index 5d32a0bfc3..3be22ca597 100644 --- a/actions/apistatusesshow.php +++ b/actions/apistatusesshow.php @@ -21,6 +21,12 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author Tom Blankenship + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,13 +37,19 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/api.php'; +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 + * @author Evan Prodromou + * @author Jeffery To + * @author Tom Blankenship + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apistatusesupdate.php b/actions/apistatusesupdate.php index 479654be8f..0d71e15128 100644 --- a/actions/apistatusesupdate.php +++ b/actions/apistatusesupdate.php @@ -21,6 +21,12 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author Tom Blankenship + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,13 +37,19 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apiauth.php'; +require_once INSTALLDIR . '/lib/apiauth.php'; /** * Updates the authenticating user's status (posts a notice). * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author Tom Blankenship + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -45,8 +57,6 @@ require_once INSTALLDIR.'/lib/apiauth.php'; class ApiStatusesUpdateAction extends ApiAuthAction { - - var $user = null; var $source = null; var $status = null; var $in_reply_to_status_id = null; diff --git a/actions/apistatusnetconfig.php b/actions/apistatusnetconfig.php index a93570698d..ed1d151bfc 100644 --- a/actions/apistatusnetconfig.php +++ b/actions/apistatusnetconfig.php @@ -21,6 +21,7 @@ * * @category API * @package StatusNet + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -42,6 +43,7 @@ require_once INSTALLDIR . '/lib/api.php'; * * @category API * @package StatusNet + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apistatusnetversion.php b/actions/apistatusnetversion.php index 6af9bdd1a1..e73ab983be 100644 --- a/actions/apistatusnetversion.php +++ b/actions/apistatusnetversion.php @@ -21,6 +21,7 @@ * * @category API * @package StatusNet + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -41,6 +42,7 @@ require_once INSTALLDIR . '/lib/api.php'; * * @category API * @package StatusNet + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -88,8 +90,8 @@ class ApiStatusnetVersionAction extends ApiAction break; default: $this->clientError( - _('API method not found!'), - 404, + _('API method not found!'), + 404, $this->format ); break; diff --git a/actions/apisubscriptions.php b/actions/apisubscriptions.php index a952e20b87..bc68dd192a 100644 --- a/actions/apisubscriptions.php +++ b/actions/apisubscriptions.php @@ -21,6 +21,8 @@ * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,7 +33,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apibareauth.php'; +require_once INSTALLDIR . '/lib/apibareauth.php'; /** * This class outputs a list of profiles as Twitter-style user and status objects. @@ -40,6 +42,8 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apitimelinefavorites.php b/actions/apitimelinefavorites.php index c85e56264d..b8ae74f137 100644 --- a/actions/apitimelinefavorites.php +++ b/actions/apitimelinefavorites.php @@ -21,8 +21,9 @@ * * @category API * @package StatusNet - * @author Zach Copley - * @copyright 2009 StatusNet, Inc. + * @author Craig Andrews + * @author Evan Prodromou + * @author Zach Copley * @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/ */ @@ -39,6 +40,8 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apitimelinefriends.php b/actions/apitimelinefriends.php index 90f3b3c064..1ea35866e2 100644 --- a/actions/apitimelinefriends.php +++ b/actions/apitimelinefriends.php @@ -21,6 +21,12 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author mac65 + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,7 +37,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apibareauth.php'; +require_once INSTALLDIR . '/lib/apibareauth.php'; /** * Returns the most recent notices (default 20) posted by the target user. @@ -39,6 +45,12 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author mac65 + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apitimelinegroup.php b/actions/apitimelinegroup.php index 2a6f35d728..5d05429185 100644 --- a/actions/apitimelinegroup.php +++ b/actions/apitimelinegroup.php @@ -21,6 +21,9 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -38,6 +41,9 @@ require_once INSTALLDIR . '/lib/api.php'; * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apitimelinementions.php b/actions/apitimelinementions.php index c25fb0a0e9..fe5ff0f28f 100644 --- a/actions/apitimelinementions.php +++ b/actions/apitimelinementions.php @@ -21,6 +21,12 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author mac65 + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,13 +37,19 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apibareauth.php'; +require_once INSTALLDIR . '/lib/apibareauth.php'; /** * Returns the most recent (default 20) mentions (status containing @nickname) * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author mac65 + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -46,7 +58,6 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; class ApiTimelineMentionsAction extends ApiBareAuthAction { - var $user = null; var $notices = null; /** diff --git a/actions/apitimelinepublic.php b/actions/apitimelinepublic.php index 4bff4adb60..58e2677348 100644 --- a/actions/apitimelinepublic.php +++ b/actions/apitimelinepublic.php @@ -21,6 +21,12 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author mac65 + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,13 +37,19 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/api.php'; +require_once INSTALLDIR . '/lib/api.php'; /** * Returns the most recent notices (default 20) posted by everybody * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author mac65 + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apitimelinetag.php b/actions/apitimelinetag.php index cf211b173c..a274daac00 100644 --- a/actions/apitimelinetag.php +++ b/actions/apitimelinetag.php @@ -21,6 +21,9 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,13 +34,16 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/api.php'; +require_once INSTALLDIR . '/lib/api.php'; /** * Returns the 20 most recent notices tagged by a given tag * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apitimelineuser.php b/actions/apitimelineuser.php index e7fac3e7a2..285735fd1a 100644 --- a/actions/apitimelineuser.php +++ b/actions/apitimelineuser.php @@ -21,6 +21,12 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author mac65 + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,7 +37,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apibareauth.php'; +require_once INSTALLDIR . '/lib/apibareauth.php'; /** * Returns the most recent notices (default 20) posted by the authenticating @@ -40,6 +46,12 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; * * @category API * @package StatusNet + * @author Craig Andrews + * @author Evan Prodromou + * @author Jeffery To + * @author mac65 + * @author Mike Cochrane + * @author Robin Millette * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ @@ -48,7 +60,6 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; class ApiTimelineUserAction extends ApiBareAuthAction { - var $user = null; var $notices = null; /** diff --git a/actions/apiuserfollowers.php b/actions/apiuserfollowers.php index 5c0243449b..e8d92a773e 100644 --- a/actions/apiuserfollowers.php +++ b/actions/apiuserfollowers.php @@ -21,6 +21,8 @@ * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,7 +33,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apibareauth.php'; +require_once INSTALLDIR . '/lib/apibareauth.php'; /** * Ouputs the authenticating user's followers (subscribers), each with @@ -40,6 +42,8 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apiuserfriends.php b/actions/apiuserfriends.php index 8a42e36b98..741a26e588 100644 --- a/actions/apiuserfriends.php +++ b/actions/apiuserfriends.php @@ -21,6 +21,8 @@ * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,7 +33,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/apibareauth.php'; +require_once INSTALLDIR . '/lib/apibareauth.php'; /** * Ouputs the authenticating user's friends (subscriptions), each with @@ -40,6 +42,8 @@ require_once INSTALLDIR.'/lib/apibareauth.php'; * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/actions/apiusershow.php b/actions/apiusershow.php index db942d1a58..b3a939b431 100644 --- a/actions/apiusershow.php +++ b/actions/apiusershow.php @@ -21,6 +21,9 @@ * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou + * @author mac65 * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -31,7 +34,7 @@ if (!defined('STATUSNET')) { exit(1); } -require_once INSTALLDIR.'/lib/api.php'; +require_once INSTALLDIR . '/lib/api.php'; /** * Ouputs information for a user, specified by ID or screen name. @@ -39,6 +42,9 @@ require_once INSTALLDIR.'/lib/api.php'; * * @category API * @package StatusNet + * @author Dan Moore + * @author Evan Prodromou + * @author mac65 * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/lib/api.php b/lib/api.php index db2d24fbd5..7a63a4a785 100644 --- a/lib/api.php +++ b/lib/api.php @@ -21,6 +21,11 @@ * * @category API * @package StatusNet + * @author Craig Andrews + * @author Dan Moore + * @author Evan Prodromou + * @author Jeffery To + * @author Toby Inkster * @author Zach Copley * @copyright 2009 StatusNet, Inc. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 @@ -36,6 +41,11 @@ if (!defined('STATUSNET')) { * * @category API * @package StatusNet + * @author Craig Andrews + * @author Dan Moore + * @author Evan Prodromou + * @author Jeffery To + * @author Toby Inkster * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/lib/apiauth.php b/lib/apiauth.php index 4e5e0ccd99..2f2e44a264 100644 --- a/lib/apiauth.php +++ b/lib/apiauth.php @@ -21,7 +21,14 @@ * * @category API * @package StatusNet - * @author Zach Copley + * @author Adrian Lang + * @author Brenda Wallace + * @author Craig Andrews + * @author Dan Moore + * @author Evan Prodromou + * @author mEDI + * @author Sarven Capadisli + * @author Zach Copley * @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/ diff --git a/lib/apibareauth.php b/lib/apibareauth.php index 0ae477f468..2d29c1ddd6 100644 --- a/lib/apibareauth.php +++ b/lib/apibareauth.php @@ -23,7 +23,14 @@ * * @category API * @package StatusNet - * @author Zach Copley + * @author Adrian Lang + * @author Brenda Wallace + * @author Craig Andrews + * @author Dan Moore + * @author Evan Prodromou + * @author mEDI + * @author Sarven Capadisli + * @author Zach Copley * @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/ @@ -41,6 +48,13 @@ require_once INSTALLDIR.'/lib/apiauth.php'; * * @category API * @package StatusNet + * @author Adrian Lang + * @author Brenda Wallace + * @author Craig Andrews + * @author Dan Moore + * @author Evan Prodromou + * @author mEDI + * @author Sarven Capadisli * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ diff --git a/lib/twitterbasicauthclient.php b/lib/twitterbasicauthclient.php index fd331fbdc9..1040d72fb6 100644 --- a/lib/twitterbasicauthclient.php +++ b/lib/twitterbasicauthclient.php @@ -36,8 +36,14 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { * * @category Integration * @package StatusNet - * @author Zach Copley - * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @author Adrian Lang + * @author Brenda Wallace + * @author Craig Andrews + * @author Dan Moore + * @author Evan Prodromou + * @author mEDI + * @author Sarven Capadisli + * @author Zach Copley * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 * @link http://status.net/ * */ From 5eaf9f7d2eebaf6f656bfbd3d04f8a17c31898d2 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Mon, 12 Oct 2009 21:21:00 -0400 Subject: [PATCH 48/49] Added a new plugin that requires a user to have a validated email address before being allowed to post notices --- .../RequireValidatedEmailPlugin.php | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 plugins/RequireValidatedEmail/RequireValidatedEmailPlugin.php diff --git a/plugins/RequireValidatedEmail/RequireValidatedEmailPlugin.php b/plugins/RequireValidatedEmail/RequireValidatedEmailPlugin.php new file mode 100644 index 0000000000..4806538a04 --- /dev/null +++ b/plugins/RequireValidatedEmail/RequireValidatedEmailPlugin.php @@ -0,0 +1,52 @@ +. + * + * @category Plugin + * @package StatusNet + * @author Craig Andrews + * @copyright 2009 Craig Andrews http://candrews.integralblue.com + * @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 RequireValidatedEmailPlugin extends Plugin +{ + function __construct() + { + parent::__construct(); + } + + function onStartNoticeSave($notice) + { + $user = User::staticGet('id', $notice->profile_id); + if (!empty($user)) { // it's a remote notice + if (empty($user->email)) { + throw new ClientException(_("You must validate your email address before posting.")); + } + } + return true; + } +} + From 16243737606d4e1f29a94e07369e69f430d3ecc8 Mon Sep 17 00:00:00 2001 From: Sarven Capadisli Date: Tue, 13 Oct 2009 11:44:56 +0000 Subject: [PATCH 49/49] Updated default theme to use the CSS Sprites method for common icons --- theme/default/css/display.css | 48 ++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 86369cb993..3993da7177 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -88,7 +88,7 @@ color:#333333; color:#000000; } #form_notice label[for=notice_data-attach] { -background:transparent url(../../base/images/icons/twotone/green/clip-01.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/icons-01.png) no-repeat 0 -328px; } #form_notice #notice_data-attach { opacity:0; @@ -150,16 +150,18 @@ background-color:#9BB43E; #export_data li a { background-repeat:no-repeat; -background-position:0 45%; } #export_data li a.rss { -background-image:url(../../base/images/icons/icon_rss.png); +background-image:url(../../base/images/icons/icons-01.png); +background-position:0 -130px; } #export_data li a.atom { -background-image:url(../../base/images/icons/icon_atom.png); +background-image:url(../../base/images/icons/icons-01.png); +background-position:0 -64px; } #export_data li a.foaf { -background-image:url(../../base/images/icons/icon_foaf.gif); +background-image:url(../../base/images/icons/icons-01.png); +background-position:0 1px; } .entity_edit a, @@ -171,7 +173,6 @@ background-image:url(../../base/images/icons/icon_foaf.gif); .form_group_unblock input.submit, .entity_nudge p, .form_make_admin input.submit { -background-position: 0 40%; background-repeat: no-repeat; background-color:transparent; } @@ -189,43 +190,48 @@ background-color:#87B4C8; } .entity_edit a { -background-image:url(../../base/images/icons/twotone/green/edit.gif); +background-image:url(../../base/images/icons/icons-01.png); +background-position: 0 -718px; } .entity_send-a-message a { -background-image:url(../../base/images/icons/twotone/green/quote.gif); +background-image:url(../../base/images/icons/icons-01.png); +background-position: 0 -849px; } .entity_nudge p, .form_user_nudge input.submit { -background-image:url(../../base/images/icons/twotone/green/mail.gif); +background-image:url(../../base/images/icons/icons-01.png); +background-position: 0 -785px; } .form_user_block input.submit, .form_user_unblock input.submit, .form_group_block input.submit, .form_group_unblock input.submit { -background-image:url(../../base/images/icons/twotone/green/shield.gif); +background-image:url(../../base/images/icons/icons-01.png); +background-position: 0 -918px; } .form_make_admin input.submit { -background-image:url(../../base/images/icons/twotone/green/admin.gif); +background-image:url(../../base/images/icons/icons-01.png); +background-position: 0 -983px; } /* NOTICES */ .notice .attachment { -background:transparent url(../../base/images/icons/twotone/green/clip-02.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/icons-01.png) no-repeat 0 -394px; } #attachments .attachment { background:none; } .notice-options .notice_reply { -background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/icons-01.png) no-repeat 0 -589px; } .notice-options form.form_favor input.submit { -background:transparent url(../../base/images/icons/twotone/green/favourite.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/icons-01.png) no-repeat 0 -457px; } .notice-options form.form_disfavor input.submit { -background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/icons-01.png) no-repeat 0 -523px; } .notice-options .notice_delete { -background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/icons-01.png) no-repeat 0 -655px; } .notices div.entry-content, @@ -262,7 +268,7 @@ background-color:rgba(200, 200, 200, 0.300); /*END: NOTICES */ #new_group a { -background:transparent url(../../base/images/icons/twotone/green/news.gif) no-repeat 0 45%; +background:transparent url(../../base/images/icons/icons-01.png) no-repeat 0 -1054px; } .pagination .nav_prev a, @@ -271,10 +277,10 @@ background-repeat:no-repeat; border-color:#C8D1D5; } .pagination .nav_prev a { -background-image:url(../../base/images/icons/twotone/green/arrow-left.gif); -background-position:10% 45%; +background-image:url(../../base/images/icons/icons-01.png); +background-position:10% -187px; } .pagination .nav_next a { -background-image:url(../../base/images/icons/twotone/green/arrow-right.gif); -background-position:90% 45%; +background-image:url(../../base/images/icons/icons-01.png); +background-position:105% -252px; }