]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Started refactoring API into individual actions
authorZach Copley <zach@status.net>
Wed, 23 Sep 2009 20:45:51 +0000 (13:45 -0700)
committerZach Copley <zach@status.net>
Wed, 23 Sep 2009 20:45:51 +0000 (13:45 -0700)
actions/apifriendstimeline.php [new file with mode: 0644]
lib/router.php
lib/twitterapi.php

diff --git a/actions/apifriendstimeline.php b/actions/apifriendstimeline.php
new file mode 100644 (file)
index 0000000..ea38ec0
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show the friends timeline
+ *
+ * PHP version 5
+ *
+ * LICENCE: This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Personal
+ * @package   StatusNet
+ * @author    Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    exit(1);
+}
+
+require_once INSTALLDIR.'/lib/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
index 2c4d63b0d794df6a1973d7c26dd77c8373576f3f..0e5fe3a54f9ac428f6ee9665f5fc273b3f95d894 100644 (file)
@@ -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
 
index d199e4dee27d657e05bcadf20c3b07200706068c..ac5c5b42397381a9d619630827c7d50b0cfcc124 100644 (file)
@@ -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";
+        }
+    }
+
 }