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"; - } - } - }