]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Merge branch '0.9.x' of git://gitorious.org/statusnet/mainline into 0.9.x
authorBrion Vibber <brion@pobox.com>
Mon, 21 Sep 2009 04:13:00 +0000 (21:13 -0700)
committerBrion Vibber <brion@pobox.com>
Mon, 21 Sep 2009 04:13:00 +0000 (21:13 -0700)
19 files changed:
actions/all.php
actions/api.php
actions/finishremotesubscribe.php
actions/twitapifriendships.php
actions/twitapistatuses.php
actions/updateprofile.php
classes/Config.php [changed mode: 0755->0644]
classes/Deleted_notice.php [changed mode: 0755->0644]
classes/statusnet.ini [changed mode: 0755->0644]
db/notice_source.sql
index.php
install.php
lib/common.php
lib/curlclient.php [new file with mode: 0644]
lib/httpclient.php [new file with mode: 0644]
lib/omb.php
lib/router.php
plugins/OpenID/OpenIDPlugin.php
theme/readme.txt

index 29a19afb6ba9d27e9b6ab406178312f4443d7752..f1786462e161e9d55cbadbb806a3362ee09269cb 100644 (file)
@@ -1,5 +1,5 @@
 <?php
-/*
+/**
  * StatusNet - the distributed open-source microblogging tool
  * Copyright (C) 2008, 2009, StatusNet, Inc.
  *
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Actions
+ * @package  Actions
+ * @author   Evan Prodromou <evan@status.net>
+ * @author   Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author   Robin Millette <millette@controlyourself.ca>
+ * @author   Adrian Lang <mail@adrianlang.de>
+ * @author   Meitar Moscovitz <meitarm@gmail.com>
+ * @author   Sarven Capadisli <csarven@status.net>
+ * @author   Craig Andrews <candrews@integralblue.com>
+ * @author   Jeffery To <jeffery.to@gmail.com>
+ * @author   Zach Copley <zach@controlyourself.ca>
+ * @license  GNU Affero General Public License http://www.gnu.org/licenses/
+ * @link     http://status.net
  */
 
-if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+    exit(1);
+}
 
 require_once INSTALLDIR.'/lib/personalgroupnav.php';
 require_once INSTALLDIR.'/lib/noticelist.php';
@@ -43,8 +59,8 @@ class AllAction extends ProfileAction
             $this->notice = $this->user->noticesWithFriends(($this->page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
         }
 
-        if($this->page > 1 && $this->notice->N == 0){
-            $this->serverError(_('No such page'),$code=404);
+        if ($this->page > 1 && $this->notice->N == 0) {
+            $this->serverError(_('No such page'), $code = 404);
         }
 
         return true;
@@ -73,20 +89,33 @@ class AllAction extends ProfileAction
 
     function getFeeds()
     {
-        return array(new Feed(Feed::RSS1,
-                              common_local_url('allrss', array('nickname' =>
-                                                               $this->user->nickname)),
-                              sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)),
-                     new Feed(Feed::RSS2,
-                              common_local_url('api', array('apiaction' => 'statuses',
-                                                            'method' => 'friends_timeline',
-                                                            'argument' => $this->user->nickname.'.rss')),
-                              sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)),
-                     new Feed(Feed::ATOM,
-                              common_local_url('api', array('apiaction' => 'statuses',
-                                                            'method' => 'friends_timeline',
-                                                            'argument' => $this->user->nickname.'.atom')),
-                              sprintf(_('Feed for friends of %s (Atom)'), $this->user->nickname)));
+        return array(
+            new Feed(Feed::RSS1,
+                common_local_url(
+                    'allrss', array(
+                        'nickname' =>
+                        $this->user->nickname)
+                ),
+                sprintf(_('Feed for friends of %s (RSS 1.0)'), $this->user->nickname)),
+            new Feed(Feed::RSS2,
+                common_local_url(
+                    'api', array(
+                        'apiaction' => 'statuses',
+                        'method' => 'friends_timeline',
+                        'argument' => $this->user->nickname.'.rss'
+                    )
+                ),
+                sprintf(_('Feed for friends of %s (RSS 2.0)'), $this->user->nickname)),
+            new Feed(Feed::ATOM,
+                common_local_url(
+                    'api', array(
+                        'apiaction' => 'statuses',
+                        'method' => 'friends_timeline',
+                        'argument' => $this->user->nickname.'.atom'
+                    )
+                ),
+                sprintf(_('Feed for friends of %s (Atom)'), $this->user->nickname))
+        );
     }
 
     function showLocalNav()
@@ -106,8 +135,7 @@ class AllAction extends ProfileAction
             } else {
                 $message .= sprintf(_('You can try to [nudge %s](../%s) from his profile or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname);
             }
-        }
-        else {
+        } else {
             $message .= sprintf(_('Why not [register an account](%%%%action.register%%%%) and then nudge %s or post a notice to his or her attention.'), $this->user->nickname);
         }
 
@@ -126,17 +154,19 @@ class AllAction extends ProfileAction
             $this->showEmptyListMessage();
         }
 
-        $this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
-                          $this->page, 'all', array('nickname' => $this->user->nickname));
+        $this->pagination(
+            $this->page > 1, $cnt > NOTICES_PER_PAGE,
+            $this->page, 'all', array('nickname' => $this->user->nickname)
+        );
     }
 
     function showPageTitle()
     {
         $user =& common_current_user();
         if ($user && ($user->id == $this->user->id)) {
-            $this->element('h1', NULL, _("You and friends"));
+            $this->element('h1', null, _("You and friends"));
         } else {
-            $this->element('h1', NULL, sprintf(_('%s and friends'), $this->user->nickname));
+            $this->element('h1', null, sprintf(_('%s and friends'), $this->user->nickname));
         }
     }
 
index c236378bcb4f2a0fcd454c74a223580785fb8641..d570bb0174a093297f4fc2e6e903e32ccd2f224a 100644 (file)
@@ -1,5 +1,5 @@
 <?php
-/*
+/**
  * StatusNet - the distributed open-source microblogging tool
  * Copyright (C) 2008, 2009, StatusNet, Inc.
  *
  *
  * You should have received a copy of the GNU Affero General Public License
  * along with this program.     If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Actions
+ * @package  Actions
+ * @author   Evan Prodromou <evan@status.net>
+ * @author   Brenda Wallace <shiny@cpan.org>
+ * @author   Jeffery To <jeffery.to@gmail.com>
+ * @author   Robin Millette <millette@controlyourself.ca>
+ * @author   Tom Adams <tom@holizz.com>
+ * @author   Christopher Vollick <psycotica0@gmail.com>
+ * @author   CiaranG <ciaran@ciarang.com>
+ * @author   Craig Andrews <candrews@integralblue.com>
+ * @author   Gina Haeussge <osd@foosel.net>
+ * @author   Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author   Sarven Capadisli <csarven@status.net>
+ * @license  GNU Affero General Public License http://www.gnu.org/licenses/
+ * @link     http://status.net
  */
 
-if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+    exit(1);
+}
 
 class ApiAction extends Action
 {
@@ -37,7 +55,7 @@ class ApiAction extends Action
         $this->api_action = $this->arg('apiaction');
         $method = $this->arg('method');
         $argument = $this->arg('argument');
-       $this->basic_auth_process_header();
+        $this->basic_auth_process_header();
 
         if (isset($argument)) {
             $cmdext = explode('.', $argument);
@@ -46,7 +64,7 @@ class ApiAction extends Action
             $this->content_type = strtolower($cmdext[1]);
         } else {
 
-            Requested format / content-type will be an extension on the method
+            //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]);
@@ -55,10 +73,10 @@ class ApiAction extends Action
         if ($this->requires_auth()) {
             if (!isset($this->auth_user)) {
 
-                This header makes basic auth go
+                //This header makes basic auth go
                 header('WWW-Authenticate: Basic realm="StatusNet API"');
 
-                If the user hits cancel -- bam!
+                //If the user hits cancel -- bam!
                 $this->show_basic_auth_error();
             } else {
                 $nickname = $this->auth_user;
@@ -69,7 +87,7 @@ class ApiAction extends Action
                     $this->user = $user;
                     $this->process_command();
                 } else {
-                    basic authentication failed
+                    //basic authentication failed
                     list($proxy, $ip) = common_client_ip();
 
                     common_log(LOG_WARNING, "Failed API auth attempt, nickname = $nickname, proxy = $proxy, ip = $ip.");
@@ -84,7 +102,7 @@ class ApiAction extends Action
                 if ($user) {
                     $this->user = $user;
                 }
-                Twitter doesn't throw an error if the user isn't found
+                //Twitter doesn't throw an error if the user isn't found
             }
 
             $this->process_command();
@@ -97,7 +115,7 @@ class ApiAction extends Action
         $actionfile = INSTALLDIR."/actions/$action.php";
 
         if (file_exists($actionfile)) {
-            require_once($actionfile);
+            include_once $actionfile;
             $action_class = ucfirst($action)."Action";
             $action_obj = new $action_class();
 
@@ -113,10 +131,10 @@ class ApiAction extends Action
 
                 call_user_func(array($action_obj, $this->api_method), $_REQUEST, $apidata);
             } else {
-                $this->clientError("API method not found!", $code=404);
+                $this->clientError("API method not found!", $code = 404);
             }
         } else {
-            $this->clientError("API method not found!", $code=404);
+            $this->clientError("API method not found!", $code = 404);
         }
     }
 
@@ -184,10 +202,11 @@ class ApiAction extends Action
             $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)) {
+            if (empty($this->api_arg)
+                && empty($id)
+                && empty($user_id)
+                && empty($screen_name)
+            ) {
                 return true;
             } else {
                 return false;
@@ -208,35 +227,29 @@ class ApiAction extends Action
 
     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;
-       }
+        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()
@@ -252,7 +265,7 @@ class ApiAction extends Action
             $this->element('request', null, $_SERVER['REQUEST_URI']);
             $this->elementEnd('hash');
             $this->endXML();
-        } else if ($this->content_type == 'json')  {
+        } 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));
index 44abbfceb793c31d9a74119cce11987643246948..b1cec66f48af55ac41de11b0fab041433cf3b093 100644 (file)
@@ -41,7 +41,7 @@ require_once INSTALLDIR.'/lib/omb.php';
  *
  * @category Action
  * @package  Laconica
- * @author   Evan Prodromou <evan@controlyourself.ca>
+ * @author   Evan Prodromou <evan@status.net>
  * @author   Robin Millette <millette@controlyourself.ca>
  * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
  * @link     http://laconi.ca/
@@ -143,67 +143,4 @@ class FinishremotesubscribeAction extends Action
                                                              $user->nickname)),
                         303);
     }
-
-    function add_avatar($profile, $url)
-    {
-        $temp_filename = tempnam(sys_get_temp_dir(), 'listener_avatar');
-        copy($url, $temp_filename);
-        $imagefile = new ImageFile($profile->id, $temp_filename);
-        $filename = Avatar::filename($profile->id,
-                                     image_type_to_extension($imagefile->type),
-                                     null,
-                                     common_timestamp());
-        rename($temp_filename, Avatar::path($filename));
-        return $profile->setOriginal($filename);
-    }
-
-    function access_token($omb)
-    {
-
-        common_debug('starting request for access token', __FILE__);
-
-        $con = omb_oauth_consumer();
-        $tok = new OAuthToken($omb['token'], $omb['secret']);
-
-        common_debug('using request token "'.$tok.'"', __FILE__);
-
-        $url = $omb['access_token_url'];
-
-        common_debug('using access token url "'.$url.'"', __FILE__);
-
-        # XXX: Is this the right thing to do? Strip off GET params and make them
-        # POST params? Seems wrong to me.
-
-        $parsed = parse_url($url);
-        $params = array();
-        parse_str($parsed['query'], $params);
-
-        $req = OAuthRequest::from_consumer_and_token($con, $tok, "POST", $url, $params);
-
-        $req->set_parameter('omb_version', OMB_VERSION_01);
-
-        # XXX: test to see if endpoint accepts this signature method
-
-        $req->sign_request(omb_hmac_sha1(), $con, $tok);
-
-        # We re-use this tool's fetcher, since it's pretty good
-
-        common_debug('posting to access token url "'.$req->get_normalized_http_url().'"', __FILE__);
-        common_debug('posting request data "'.$req->to_postdata().'"', __FILE__);
-
-        $fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
-        $result = $fetcher->post($req->get_normalized_http_url(),
-                                 $req->to_postdata(),
-                                 array('User-Agent: StatusNet/' . STATUSNET_VERSION));
-
-        common_debug('got result: "'.print_r($result,true).'"', __FILE__);
-
-        if ($result->status != 200) {
-            return null;
-        }
-
-        parse_str($result->body, $return);
-
-        return array($return['oauth_token'], $return['oauth_token_secret']);
-    }
 }
index f2ea46910ee92edbf0c0618b1e51e66787085e0a..eea8945c393402d7080bda3534f38116ffe9bc7b 100644 (file)
@@ -99,6 +99,12 @@ class TwitapifriendshipsAction extends TwitterapiAction
         $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;
index ad6654dff54321f7d0a5c0089791cd60e75134ee..2f10ff966c8113a34477e4b7e2832945f447b385 100644 (file)
@@ -136,6 +136,11 @@ class TwitapistatusesAction extends TwitterapiAction
 
     }
 
+    function home_timeline($args, $apidata)
+    {
+        call_user_func(array($this, 'friends_timeline'), $args, $apidata);
+    }
+
     function user_timeline($args, $apidata)
     {
         parent::handle($args);
index 7f7dd75fef14481c8992d6e3ae7db711533eab9c..3cec9523cdff1fd3c1376592121e8cf21f52dacb 100644 (file)
@@ -38,7 +38,7 @@ require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
  *
  * @category Action
  * @package  Laconica
- * @author   Evan Prodromou <evan@controlyourself.ca>
+ * @author   Evan Prodromou <evan@status.net>
  * @author   Robin Millette <millette@controlyourself.ca>
  * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
  * @link     http://laconi.ca/
@@ -55,46 +55,13 @@ class UpdateprofileAction extends Action
      */
     function prepare($argarray)
     {
-        $version = $req->get_parameter('omb_version');
-        if ($version != OMB_VERSION_01) {
-            $this->clientError(_('Unsupported OMB version'), 400);
-            return false;
-        }
-        # First, check to see if listenee exists
-        $listenee =  $req->get_parameter('omb_listenee');
-        $remote = Remote_profile::staticGet('uri', $listenee);
-        if (!$remote) {
-            $this->clientError(_('Profile unknown'), 404);
-            return false;
-        }
-        # Second, check to see if they should be able to post updates!
-        # We see if there are any subscriptions to that remote user with
-        # the given token.
-
-        $sub = new Subscription();
-        $sub->subscribed = $remote->id;
-        $sub->token = $token->key;
-        if (!$sub->find(true)) {
-            $this->clientError(_('You did not send us that profile'), 403);
-            return false;
-        }
-
-        $profile = Profile::staticGet('id', $remote->id);
-        if (!$profile) {
-            # This one is our fault
-            $this->serverError(_('Remote profile with no matching profile'), 500);
-            return false;
-        }
-        $nickname = $req->get_parameter('omb_listenee_nickname');
-        if ($nickname && !Validate::string($nickname, array('min_length' => 1,
-                                                            'max_length' => 64,
-                                                            'format' => NICKNAME_FMT))) {
-            $this->clientError(_('Nickname must have only lowercase letters and numbers and no spaces.'));
-            return false;
-        }
-        $license = $req->get_parameter('omb_listenee_license');
-        if ($license && !common_valid_http_url($license)) {
-            $this->clientError(sprintf(_("Invalid license URL '%s'"), $license));
+        parent::prepare($argarray);
+        $license      = $_POST['omb_listenee_license'];
+        $site_license = common_config('license', 'url');
+        if (!common_compatible_license($license, $site_license)) {
+            $this->clientError(sprintf(_('Listenee stream license â€˜%s’ is not '.
+                                         'compatible with site license â€˜%s’.'),
+                                       $license, $site_license));
             return false;
         }
         return true;
@@ -113,4 +80,4 @@ class UpdateprofileAction extends Action
             return;
         }
     }
-}
\ No newline at end of file
+}
old mode 100755 (executable)
new mode 100644 (file)
index 5bec13f..92f237d
@@ -17,7 +17,9 @@
  * along with this program.     If not, see <http://www.gnu.org/licenses/>.
  */
 
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET')) {
+    exit(1);
+}
 
 /**
  * Table Definition for config
old mode 100755 (executable)
new mode 100644 (file)
index 474d0b6..64dc85d
@@ -17,7 +17,9 @@
  * along with this program.     If not, see <http://www.gnu.org/licenses/>.
  */
 
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET')) {
+    exit(1);
+}
 
 /**
  * Table Definition for notice
old mode 100755 (executable)
new mode 100644 (file)
index f590d1b97a7fa2cd83017b309688e372b37c99d3..2657763f440ba59b9ef45312ab97c81f084a66e2 100644 (file)
@@ -21,6 +21,7 @@ VALUES
     ('identichat','identichat','http://identichat.prosody.im/', now()),
     ('IdentiFox','IdentiFox','http://www.bitbucket.org/uncryptic/identifox/', now()),
     ('identitwitch','IdentiTwitch','http://richfish.org/identitwitch/', now()),
+    ('Jiminy','Jiminy','http://code.google.com/p/jiminy/', now()),
     ('LaTwit','LaTwit','http://latwit.mac65.com/', now()),
     ('LiveTweeter', 'LiveTweeter', 'http://addons.songbirdnest.com/addon/1204', now()),
     ('livetweeter', 'livetweeter', 'http://addons.songbirdnest.com/addon/1204', now()),
index e2296549f3efd96e5b5ff284265ad14152ff5d08..8ff67d19d9165def2675d5c6955b435f8b884d8d 100644 (file)
--- a/index.php
+++ b/index.php
  *
  * 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 StatusNet
+ * @package  StatusNet
+ * @author   Brenda Wallace <shiny@cpan.org>
+ * @author   Christopher Vollick <psycotica0@gmail.com>
+ * @author   CiaranG <ciaran@ciarang.com>
+ * @author   Craig Andrews <candrews@integralblue.com>
+ * @author   Evan Prodromou <evan@controlezvous.ca>
+ * @author   Gina Haeussge <osd@foosel.net>
+ * @author   Jeffery To <jeffery.to@gmail.com>
+ * @author   Mike Cochrane <mikec@mikenz.geek.nz>
+ * @author   Robin Millette <millette@controlyourself.ca>
+ * @author   Sarven Capadisli <csarven@controlyourself.ca>
+ * @author   Tom Adams <tom@holizz.com>
+ * 
+ * @license  GNU Affero General Public License http://www.gnu.org/licenses/
  */
 
 define('INSTALLDIR', dirname(__FILE__));
@@ -29,7 +45,8 @@ $action = null;
 function getPath($req)
 {
     if ((common_config('site', 'fancy') || !array_key_exists('PATH_INFO', $_SERVER))
-        && array_key_exists('p', $req)) {
+        && array_key_exists('p', $req)
+    ) {
         return $req['p'];
     } else if (array_key_exists('PATH_INFO', $_SERVER)) {
         return $_SERVER['PATH_INFO'];
@@ -45,28 +62,35 @@ function handleError($error)
     }
 
     $logmsg = "PEAR error: " . $error->getMessage();
-    if(common_config('site', 'logdebug')) {
+    if (common_config('site', 'logdebug')) {
         $logmsg .= " : ". $error->getDebugInfo();
     }
     common_log(LOG_ERR, $logmsg);
-    if(common_config('site', 'logdebug')) {
+    if (common_config('site', 'logdebug')) {
         $bt = $error->getBacktrace();
         foreach ($bt as $line) {
             common_log(LOG_ERR, $line);
         }
     }
-    if ($error instanceof DB_DataObject_Error ||
-        $error instanceof DB_Error) {
-        $msg = sprintf(_('The database for %s isn\'t responding correctly, '.
-                         'so the site won\'t work properly. '.
-                         'The site admins probably know about the problem, '.
-                         'but you can contact them at %s to make sure. '.
-                         'Otherwise, wait a few minutes and try again.'),
-                       common_config('site', 'name'),
-                       common_config('site', 'email'));
+    if ($error instanceof DB_DataObject_Error
+        || $error instanceof DB_Error
+    ) {
+        $msg = sprintf(
+            _(
+                'The database for %s isn\'t responding correctly, '.
+                'so the site won\'t work properly. '.
+                'The site admins probably know about the problem, '.
+                'but you can contact them at %s to make sure. '.
+                'Otherwise, wait a few minutes and try again.'
+            ),
+            common_config('site', 'name'),
+            common_config('site', 'email')
+        );
     } else {
-        $msg = _('An important error occured, probably related to email setup. '.
-                 'Check logfiles for more info..');
+        $msg = _(
+            'An important error occured, probably related to email setup. '.
+            'Check logfiles for more info..'
+        );
     }
 
     $dac = new DBErrorAction($msg, 500);
@@ -127,10 +151,11 @@ function main()
         $_lighty_url = @parse_url($_lighty_url);
 
         if ($_lighty_url['path'] != '/index.php' && $_lighty_url['path'] != '/') {
-            $_lighty_path = preg_replace('/^'.preg_quote(common_config('site','path')).'\//', '', substr($_lighty_url['path'], 1));
+            $_lighty_path = preg_replace('/^'.preg_quote(common_config('site', 'path')).'\//', '', substr($_lighty_url['path'], 1));
             $_SERVER['QUERY_STRING'] = 'p='.$_lighty_path;
-            if ($_lighty_url['query'])
+            if ($_lighty_url['query']) {
                 $_SERVER['QUERY_STRING'] .= '&'.$_lighty_url['query'];
+            }
             parse_str($_lighty_url['query'], $_lighty_query);
             foreach ($_lighty_query as $key => $val) {
                 $_GET[$key] = $_REQUEST[$key] = $val;
@@ -141,7 +166,7 @@ function main()
     $_SERVER['REDIRECT_URL'] = preg_replace("/\?.+$/", "", $_SERVER['REQUEST_URI']);
 
     // quick check for fancy URL auto-detection support in installer.
-    if (isset($_SERVER['REDIRECT_URL']) && (preg_replace("/^\/$/","",(dirname($_SERVER['REQUEST_URI']))) . '/check-fancy') === $_SERVER['REDIRECT_URL']) {
+    if (isset($_SERVER['REDIRECT_URL']) && (preg_replace("/^\/$/", "", (dirname($_SERVER['REQUEST_URI']))) . '/check-fancy') === $_SERVER['REDIRECT_URL']) {
         die("Fancy URL support detection succeeded. We suggest you enable this to get fancy (pretty) URLs.");
     }
     global $user, $action;
@@ -149,8 +174,12 @@ function main()
     Snapshot::check();
 
     if (!_have_config()) {
-        $msg = sprintf(_("No configuration file found. Try running ".
-                         "the installation program first."));
+        $msg = sprintf(
+            _(
+                "No configuration file found. Try running ".
+                "the installation program first."
+            )
+        );
         $sac = new ServerErrorAction($msg);
         $sac->showPage();
         return;
@@ -196,9 +225,10 @@ function main()
     // If the site is private, and they're not on one of the "public"
     // parts of the site, redirect to login
 
-    if (!$user && common_config('site', 'private') &&
-        !isLoginAction($action) &&
-        !preg_match('/rss$/', $action)) {
+    if (!$user && common_config('site', 'private')
+        && !isLoginAction($action)
+        && !preg_match('/rss$/', $action)
+    ) {
         common_redirect(common_local_url('login'));
         return;
     }
index e828fa814b26b01f87fc95234d9de379dde0b9a7..46248c7891b2ab503f4d5faff524e09d183da6fd 100644 (file)
  *
  * 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 Installation
+ * @package  Installation
+ *
+ * @author   Adrian Lang <mail@adrianlang.de>
+ * @author   Brenda Wallace <shiny@cpan.org>
+ * @author   Brett Taylor <brett@webfroot.co.nz>
+ * @author   Brion Vibber <brion@pobox.com>
+ * @author   CiaranG <ciaran@ciarang.com>
+ * @author   Craig Andrews <candrews@integralblue.com>
+ * @author   Eric Helgeson <helfire@Erics-MBP.local>
+ * @author   Evan Prodromou <evan@status.net>
+ * @author   Robin Millette <millette@controlyourself.ca>
+ * @author   Sarven Capadisli <csarven@status.net>
+ * @author   Tom Adams <tom@holizz.com>
+ * @license  GNU Affero General Public License http://www.gnu.org/licenses/
+ * @version  0.9
+ * @link     http://status.net
  */
 
 define('INSTALLDIR', dirname(__FILE__));
@@ -181,17 +199,34 @@ $external_libraries=array(
         'check_class'=>'Validate'
     )
 );
+$dbModules = array(
+    'mysql' => array(
+        'name' => 'MySQL',
+        'check_module' => 'mysql', // mysqli?
+        'installer' => 'mysql_db_installer',
+    ),
+    'pgsql' => array(
+        'name' => 'PostgreSQL',
+        'check_module' => 'pgsql',
+        'installer' => 'pgsql_db_installer',
+    ),
+);
 
+/**
+ * the actual installation.
+ * If call libraries are present, then install
+ *
+ * @return void
+ */
 function main()
 {
-    if (!checkPrereqs())
-    {
+    if (!checkPrereqs()) {
         return;
     }
-    
-    if( $_GET['checklibs'] ){
+
+    if (!empty($_GET['checklibs'])) {
         showLibs();
-    }else{
+    } else {
         if ($_SERVER['REQUEST_METHOD'] == 'POST') {
             handlePost();
         } else {
@@ -200,33 +235,44 @@ function main()
     }
 }
 
+/**
+ * checks if an external libary is present
+ *
+ * @param string $external_library Name of library
+ *
+ * @return boolean indicates if library present
+ */
 function haveExternalLibrary($external_library)
 {
-    if(isset($external_library['include']) && ! include_once($external_library['include'])){
+    if (isset($external_library['include']) && ! @include_once $external_library['include'] ) {
         return false;
     }
-    if(isset($external_library['check_function']) && ! function_exists($external_library['check_function'])){
+    if (isset($external_library['check_function']) && ! function_exists($external_library['check_function'])) {
         return false;
     }
-    if(isset($external_library['check_class']) && ! class_exists($external_library['check_class'])){
+    if (isset($external_library['check_class']) && ! class_exists($external_library['check_class'])) {
         return false;
     }
     return true;
 }
 
+/**
+ * Check if all is ready for installation
+ *
+ * @return void
+ */
 function checkPrereqs()
 {
-       $pass = true;
+    $pass = true;
 
     if (file_exists(INSTALLDIR.'/config.php')) {
-         ?><p class="error">Config file &quot;config.php&quot; already exists.</p>
-         <?php
+         printf('<p class="error">Config file &quot;config.php&quot; already exists.</p>');
         $pass = false;
     }
 
     if (version_compare(PHP_VERSION, '5.2.3', '<')) {
-            ?><p class="error">Require PHP version 5.2.3 or greater.</p><?php
-                   $pass = false;
+        printf('<p class="error">Require PHP version 5.2.3 or greater.</p>');
+        $pass = false;
     }
 
     $reqs = array('gd', 'curl',
@@ -234,37 +280,52 @@ function checkPrereqs()
 
     foreach ($reqs as $req) {
         if (!checkExtension($req)) {
-            ?><p class="error">Cannot load required extension: <code><?php echo $req; ?></code></p><?php
-                   $pass = false;
+            printf('<p class="error">Cannot load required extension: <code>%s</code></p>', $req);
+            $pass = false;
+        }
+    }
+    // Make sure we have at least one database module available
+    global $dbModules;
+    $missingExtensions = array();
+    foreach ($dbModules as $type => $info) {
+        if (!checkExtension($info['check_module'])) {
+            $missingExtensions[] = $info['check_module'];
+        }
+    }
+
+    if (count($missingExtensions) == count($dbModules)) {
+        $req = implode(', ', $missingExtensions);
+        printf('<p class="error">Cannot find mysql or pgsql extension. You need one or the other.');
+        $pass = false;
+    }
+
+    if (!is_writable(INSTALLDIR)) {
+        printf('<p class="error">Cannot write config file to: <code>%s</code></p>', INSTALLDIR);
+        printf('<p>On your server, try this command: <code>chmod a+w %s</code>', INSTALLDIR);
+        $pass = false;
+    }
+
+    // Check the subdirs used for file uploads
+    $fileSubdirs = array('avatar', 'background', 'file');
+    foreach ($fileSubdirs as $fileSubdir) {
+        $fileFullPath = INSTALLDIR."/$fileSubdir/";
+        if (!is_writable($fileFullPath)) {
+            printf('<p class="error">Cannot write to %s directory: <code>%s</code></p>', $fileSubdir, $fileFullPath);
+            printf('<p>On your server, try this command: <code>chmod a+w %s</code></p>', $fileFullPath);
+            $pass = false;
         }
     }
-    if (!checkExtension('pgsql') && !checkExtension('mysql')) {
-      ?><p class="error">Cannot find mysql or pgsql extension. You need one or the other: <code><?php echo $req; ?></code></p><?php
-                    $pass = false;
-    }
-
-       if (!is_writable(INSTALLDIR)) {
-         ?><p class="error">Cannot write config file to: <code><?php echo INSTALLDIR; ?></code></p>
-              <p>On your server, try this command: <code>chmod a+w <?php echo INSTALLDIR; ?></code>
-         <?php
-            $pass = false;
-       }
-
-       // Check the subdirs used for file uploads
-       $fileSubdirs = array('avatar', 'background', 'file');
-       foreach ($fileSubdirs as $fileSubdir) {
-               $fileFullPath = INSTALLDIR."/$fileSubdir/";
-               if (!is_writable($fileFullPath)) {
-            ?><p class="error">Cannot write <?php echo $fileSubdir; ?> directory: <code><?php echo $fileFullPath; ?></code></p>
-                      <p>On your server, try this command: <code>chmod a+w <?php echo $fileFullPath; ?></code></p>
-            <?php
-                    $pass = false;
-               }
-       }
-
-       return $pass;
+
+    return $pass;
 }
 
+/**
+ * Checks if a php extension is both installed and loaded
+ *
+ * @param string $name of extension to check
+ *
+ * @return boolean whether extension is installed and loaded
+ */
 function checkExtension($name)
 {
     if (!extension_loaded($name)) {
@@ -275,15 +336,20 @@ function checkExtension($name)
     return true;
 }
 
+/**
+ * Show list of libraries
+ *
+ * @return void
+ */
 function showLibs()
 {
     global $external_libraries;
     $present_libraries=array();
     $absent_libraries=array();
-    foreach($external_libraries as $external_library){
-        if(haveExternalLibrary($external_library)){
+    foreach ($external_libraries as $external_library) {
+        if (haveExternalLibrary($external_library)) {
             $present_libraries[]=$external_library;
-        }else{
+        } else {
             $absent_libraries[]=$external_library;
         }
     }
@@ -298,22 +364,21 @@ function showLibs()
     <h2>Absent Libraries</h2>
     <ul id="absent_libraries">
 E_O_T;
-    foreach($absent_libraries as $library)
-    {
+    foreach ($absent_libraries as $library) {
         echo '<li>';
-        if($library['url']){
+        if (isset($library['url'])) {
             echo '<a href=">'.$library['url'].'">'.htmlentities($library['name']).'</a>';
-        }else{
+        } else {
             echo htmlentities($library['name']);
         }
         echo '<ul>';
-        if($library['deb']){
+        if (isset($library['deb'])) {
             echo '<li class="deb package">deb: <a href="apt:' . urlencode($library['deb']) . '">' . htmlentities($library['deb']) . '</a></li>';
         }
-        if($library['rpm']){
+        if (isset($library['rpm'])) {
             echo '<li class="rpm package">rpm: ' . htmlentities($library['rpm']) . '</li>';
         }
-        if($library['pear']){
+        if (isset($library['pear'])) {
             echo '<li class="pear package">pear: ' . htmlentities($library['pear']) . '</li>';
         }
         echo '</ul>';
@@ -323,12 +388,11 @@ E_O_T;
     <h2>Installed Libraries</h2>
     <ul id="present_libraries">
 E_O_T;
-    foreach($present_libraries as $library)
-    {
+    foreach ($present_libraries as $library) {
         echo '<li>';
-        if($library['url']){
+        if ($library['url']) {
             echo '<a href=">'.$library['url'].'">'.htmlentities($library['name']).'</a>';
-        }else{
+        } else {
             echo htmlentities($library['name']);
         }
         echo '</li>';
@@ -340,6 +404,15 @@ E_O_T;
 
 function showForm()
 {
+    global $dbModules;
+    $dbRadios = '';
+    $checked = 'checked="checked" '; // Check the first one which exists
+    foreach ($dbModules as $type => $info) {
+        if (checkExtension($info['check_module'])) {
+            $dbRadios .= "<input type=\"radio\" name=\"dbtype\" id=\"dbtype-$type\" value=\"$type\" $checked/> $info[name]<br />\n";
+            $checked = '';
+        }
+    }
     echo<<<E_O_T
         </ul>
     </dd>
@@ -376,8 +449,7 @@ function showForm()
             <li>
 
                 <label for="dbtype">Type</label>
-                <input type="radio" name="dbtype" id="fancy-mysql" value="mysql" checked='checked' /> MySQL<br />
-                <input type="radio" name="dbtype" id="dbtype-pgsql" value="pgsql" /> PostgreSQL<br />
+                $dbRadios
                 <p class="form_guide">Database type</p>
             </li>
 
@@ -406,17 +478,11 @@ E_O_T;
 
 function updateStatus($status, $error=false)
 {
-?>
-                <li <?php echo ($error) ? 'class="error"': ''; ?>><?php echo $status;?></li>
-
-<?php
+    echo '<li' . ($error ? ' class="error"': '' ) . ">$status</li>";
 }
 
 function handlePost()
 {
-?>
-
-<?php
     $host     = $_POST['host'];
     $dbtype   = $_POST['dbtype'];
     $database = $_POST['database'];
@@ -427,55 +493,41 @@ function handlePost()
     $server = $_SERVER['HTTP_HOST'];
     $path = substr(dirname($_SERVER['PHP_SELF']), 1);
 
-?>
+    echo <<<STR
     <dl class="system_notice">
         <dt>Page notice</dt>
         <dd>
             <ul>
-<?php
-       $fail = false;
+STR;
+    $fail = false;
 
     if (empty($host)) {
         updateStatus("No hostname specified.", true);
-               $fail = true;
+        $fail = true;
     }
 
     if (empty($database)) {
         updateStatus("No database specified.", true);
-               $fail = true;
+        $fail = true;
     }
 
     if (empty($username)) {
         updateStatus("No username specified.", true);
-               $fail = true;
+        $fail = true;
     }
 
-//     if (empty($password)) {
-//         updateStatus("No password specified.", true);
-//             $fail = true;
-//     }
-
     if (empty($sitename)) {
         updateStatus("No sitename specified.", true);
-               $fail = true;
+        $fail = true;
     }
 
-    if($fail){
-            showForm();
+    if ($fail) {
+        showForm();
         return;
     }
 
-    // FIXME: use PEAR::DB or PDO instead of our own switch
-
-    switch($dbtype) {
-        case 'mysql':
-            $db = mysql_db_installer($host, $database, $username, $password);
-            break;
-        case 'pgsql':
-            $db = pgsql_db_installer($host, $database, $username, $password);
-            break;
-        default:
-    }
+    global $dbModules;
+    $db = call_user_func($dbModules[$dbtype]['installer'], $host, $database, $username, $password);
 
     if (!$db) {
         // database connection failed, do not move on to create config file.
@@ -498,112 +550,110 @@ function handlePost()
 
     updateStatus("StatusNet has been installed at $link");
     updateStatus("You can visit your <a href='$link'>new StatusNet site</a>.");
-?>
-
-<?php
 }
 
-function pgsql_db_installer($host, $database, $username, $password) {
-  $connstring = "dbname=$database host=$host user=$username";
-
-  //No password would mean trust authentication used.
-  if (!empty($password)) {
-    $connstring .= " password=$password";
-  }
-  updateStatus("Starting installation...");
-  updateStatus("Checking database...");
-  $conn = pg_connect($connstring);
-
-  if ($conn ===false) {
-    updateStatus("Failed to connect to database: $connstring");
-    showForm();
-    return false;
-  }
-
-  //ensure database encoding is UTF8
-  $record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding'));
-  if ($record->server_encoding != 'UTF8') {
-    updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
-    showForm();
-    return false;
-  }
-
-  updateStatus("Running database script...");
-  //wrap in transaction;
-  pg_query($conn, 'BEGIN');
-  $res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql');
-
-  if ($res === false) {
-      updateStatus("Can't run database script.", true);
-      showForm();
-      return false;
-  }
-  foreach (array('sms_carrier' => 'SMS carrier',
+function Pgsql_Db_installer($host, $database, $username, $password)
+{
+    $connstring = "dbname=$database host=$host user=$username";
+
+    //No password would mean trust authentication used.
+    if (!empty($password)) {
+        $connstring .= " password=$password";
+    }
+    updateStatus("Starting installation...");
+    updateStatus("Checking database...");
+    $conn = pg_connect($connstring);
+
+    if ($conn ===false) {
+        updateStatus("Failed to connect to database: $connstring");
+        showForm();
+        return false;
+    }
+
+    //ensure database encoding is UTF8
+    $record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding'));
+    if ($record->server_encoding != 'UTF8') {
+        updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
+        showForm();
+        return false;
+    }
+
+    updateStatus("Running database script...");
+    //wrap in transaction;
+    pg_query($conn, 'BEGIN');
+    $res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql');
+
+    if ($res === false) {
+        updateStatus("Can't run database script.", true);
+        showForm();
+        return false;
+    }
+    foreach (array('sms_carrier' => 'SMS carrier',
                 'notice_source' => 'notice source',
                 'foreign_services' => 'foreign service')
           as $scr => $name) {
-      updateStatus(sprintf("Adding %s data to database...", $name));
-      $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql');
-      if ($res === false) {
-          updateStatus(sprintf("Can't run %d script.", $name), true);
-          showForm();
-          return false;
-      }
-  }
-  pg_query($conn, 'COMMIT');
-
-  if (empty($password)) {
-    $sqlUrl = "pgsql://$username@$host/$database";
-  }
-  else {
-    $sqlUrl = "pgsql://$username:$password@$host/$database";
-  }
-
-  $db = array('type' => 'pgsql', 'database' => $sqlUrl);
-
-  return $db;
+        updateStatus(sprintf("Adding %s data to database...", $name));
+        $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql');
+        if ($res === false) {
+            updateStatus(sprintf("Can't run %d script.", $name), true);
+            showForm();
+            return false;
+        }
+    }
+    pg_query($conn, 'COMMIT');
+
+    if (empty($password)) {
+        $sqlUrl = "pgsql://$username@$host/$database";
+    } else {
+        $sqlUrl = "pgsql://$username:$password@$host/$database";
+    }
+
+    $db = array('type' => 'pgsql', 'database' => $sqlUrl);
+
+    return $db;
 }
 
-function mysql_db_installer($host, $database, $username, $password) {
-  updateStatus("Starting installation...");
-  updateStatus("Checking database...");
-
-  $conn = mysql_connect($host, $username, $password);
-  if (!$conn) {
-      updateStatus("Can't connect to server '$host' as '$username'.", true);
-      showForm();
-      return false;
-  }
-  updateStatus("Changing to database...");
-  $res = mysql_select_db($database, $conn);
-  if (!$res) {
-      updateStatus("Can't change to database.", true);
-      showForm();
-      return false;
-  }
-  updateStatus("Running database script...");
-  $res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn);
-  if ($res === false) {
-      updateStatus("Can't run database script.", true);
-      showForm();
-      return false;
-  }
-  foreach (array('sms_carrier' => 'SMS carrier',
+function Mysql_Db_installer($host, $database, $username, $password)
+{
+    updateStatus("Starting installation...");
+    updateStatus("Checking database...");
+
+    $conn = mysql_connect($host, $username, $password);
+    if (!$conn) {
+        updateStatus("Can't connect to server '$host' as '$username'.", true);
+        showForm();
+        return false;
+    }
+    updateStatus("Changing to database...");
+    $res = mysql_select_db($database, $conn);
+    if (!$res) {
+        updateStatus("Can't change to database.", true);
+        showForm();
+        return false;
+    }
+    updateStatus("Running database script...");
+    $res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn);
+    if ($res === false) {
+        updateStatus("Can't run database script.", true);
+        showForm();
+        return false;
+    }
+    foreach (array('sms_carrier' => 'SMS carrier',
                 'notice_source' => 'notice source',
                 'foreign_services' => 'foreign service')
           as $scr => $name) {
-      updateStatus(sprintf("Adding %s data to database...", $name));
-      $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn);
-      if ($res === false) {
-          updateStatus(sprintf("Can't run %d script.", $name), true);
-          showForm();
-          return false;
-      }
-  }
-
-      $sqlUrl = "mysqli://$username:$password@$host/$database";
-      $db = array('type' => 'mysql', 'database' => $sqlUrl);
-      return $db;
+        updateStatus(sprintf("Adding %s data to database...", $name));
+        $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn);
+        if ($res === false) {
+            updateStatus(sprintf("Can't run %d script.", $name), true);
+            showForm();
+            return false;
+        }
+    }
+
+    $sqlUrl = "mysqli://$username:$password@$host/$database";
+    $db = array('type' => 'mysql', 'database' => $sqlUrl);
+    return $db;
 }
 
 function writeConf($sitename, $server, $path, $fancy, $db)
@@ -634,7 +684,16 @@ function writeConf($sitename, $server, $path, $fancy, $db)
     return $res;
 }
 
-function runDbScript($filename, $conn, $type = 'mysql')
+/**
+ * Install schema into the database
+ *
+ * @param string $filename location of database schema file
+ * @param dbconn $conn     connection to database
+ * @param string $type     type of database, currently mysql or pgsql
+ *
+ * @return boolean - indicating success or failure
+ */
+function runDbScript($filename, $conn, $type = 'mysqli')
 {
     $sql = trim(file_get_contents($filename));
     $stmts = explode(';', $sql);
@@ -645,7 +704,7 @@ function runDbScript($filename, $conn, $type = 'mysql')
         }
         // FIXME: use PEAR::DB or PDO instead of our own switch
         switch ($type) {
-        case 'mysql':
+        case 'mysqli':
             $res = mysql_query($stmt, $conn);
             if ($res === false) {
                 $error = mysql_error();
index 3b21b548cf9ef81ca0cb689b6bfd879e08117a90..194eb568f7d1a0ff2b7525599fd196443ee0bd78 100644 (file)
@@ -284,6 +284,8 @@ $config =
         array('contentlimit' => null),
         'message' =>
         array('contentlimit' => null),
+        'http' =>
+        array('client' => 'curl'), // XXX: should this be the default?
         );
 
 $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options');
diff --git a/lib/curlclient.php b/lib/curlclient.php
new file mode 100644 (file)
index 0000000..36fc7d1
--- /dev/null
@@ -0,0 +1,179 @@
+n<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Utility class for wrapping Curl
+ *
+ * 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  HTTP
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@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);
+}
+
+define(CURLCLIENT_VERSION, "0.1");
+
+/**
+ * Wrapper for Curl
+ *
+ * Makes Curl HTTP client calls within our HTTPClient framework
+ *
+ * @category HTTP
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+
+class CurlClient extends HTTPClient
+{
+    function __construct()
+    {
+    }
+
+    function head($url, $headers=null)
+    {
+        $ch = curl_init($url);
+
+        $this->setup($ch);
+
+        curl_setopt_array($ch,
+                          array(CURLOPT_NOBODY => true));
+
+        if (!is_null($headers)) {
+            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+        }
+
+        $result = curl_exec($ch);
+
+        curl_close($ch);
+
+        return $this->parseResults($result);
+    }
+
+    function get($url, $headers=null)
+    {
+        $ch = curl_init($url);
+
+        $this->setup($ch);
+
+        if (!is_null($headers)) {
+            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+        }
+
+        $result = curl_exec($ch);
+
+        curl_close($ch);
+
+        return $this->parseResults($result);
+    }
+
+    function post($url, $headers=null, $body=null)
+    {
+        $ch = curl_init($url);
+
+        $this->setup($ch);
+
+        curl_setopt($ch, CURLOPT_POST, true);
+
+        if (!is_null($body)) {
+            curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
+        }
+
+        if (!is_null($headers)) {
+            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+        }
+
+        $result = curl_exec($ch);
+
+        curl_close($ch);
+
+        return $this->parseResults($result);
+    }
+
+    function setup($ch)
+    {
+        curl_setopt_array($ch,
+                          array(CURLOPT_USERAGENT => $this->userAgent(),
+                                CURLOPT_HEADER => true,
+                                CURLOPT_RETURNTRANSFER => true));
+    }
+
+    function userAgent()
+    {
+        $version = curl_version();
+        return parent::userAgent() . " CurlClient/".CURLCLIENT_VERSION . " cURL/" . $version['version'];
+    }
+
+    function parseResults($results)
+    {
+        $resp = new HTTPResponse();
+
+        $lines = explode("\r\n", $results);
+
+        if (preg_match("#^HTTP/1.[01] (\d\d\d) .+$#", $lines[0], $match)) {
+            $resp->code = $match[1];
+        } else {
+            throw Exception("Bad format: initial line is not HTTP status line");
+        }
+
+        $lastk = null;
+
+        for ($i = 1; $i < count($lines); $i++) {
+            $l =& $lines[$i];
+            if (mb_strlen($l) == 0) {
+                $resp->body = implode("\r\n", array_slice($lines, $i + 1));
+                break;
+            }
+            if (preg_match("#^(\S+):\s+(.*)$#", $l, $match)) {
+                $k = $match[1];
+                $v = $match[2];
+
+                if (array_key_exists($k, $resp->headers)) {
+                    if (is_array($resp->headers[$k])) {
+                        $resp->headers[$k][] = $v;
+                    } else {
+                        $resp->headers[$k] = array($resp->headers[$k], $v);
+                    }
+                } else {
+                    $resp->headers[$k] = $v;
+                }
+                $lastk = $k;
+            } else if (preg_match("#^\s+(.*)$#", $l, $match)) {
+                // continuation line
+                if (is_null($lastk)) {
+                    throw Exception("Bad format: initial whitespace in headers");
+                }
+                $h =& $resp->headers[$lastk];
+                if (is_array($h)) {
+                    $n = count($h);
+                    $h[$n-1] .= $match[1];
+                } else {
+                    $h .= $match[1];
+                }
+            }
+        }
+
+        return $resp;
+    }
+}
diff --git a/lib/httpclient.php b/lib/httpclient.php
new file mode 100644 (file)
index 0000000..c8c8ae5
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Utility for doing HTTP-related things
+ *
+ * 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  Action
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@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);
+}
+
+/**
+ * Useful structure for HTTP responses
+ *
+ * We make HTTP calls in several places, and we have several different
+ * ways of doing them. This class hides the specifics of what underlying
+ * library (curl or PHP-HTTP or whatever) that's used.
+ *
+ * @category HTTP
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+
+class HTTPResponse
+{
+    public $code = null;
+    public $headers = null;
+    public $body = null;
+}
+
+/**
+ * Utility class for doing HTTP client stuff
+ *
+ * We make HTTP calls in several places, and we have several different
+ * ways of doing them. This class hides the specifics of what underlying
+ * library (curl or PHP-HTTP or whatever) that's used.
+ *
+ * @category HTTP
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link     http://status.net/
+ */
+
+class HTTPClient
+{
+    static $_client = null;
+
+    static function start()
+    {
+        if (!is_null(self::$_client)) {
+            return self::$_client;
+        }
+
+        $type = common_config('http', 'client');
+
+        switch ($type) {
+         case 'curl':
+            self::$_client = new CurlClient();
+            break;
+         default:
+            throw new Exception("Unknown HTTP client type '$type'");
+            break;
+        }
+
+        return self::$_client;
+    }
+
+    function head($url, $headers)
+    {
+        throw new Exception("HEAD method unimplemented");
+    }
+
+    function get($url, $headers)
+    {
+        throw new Exception("GET method unimplemented");
+    }
+
+    function post($url, $headers, $body)
+    {
+        throw new Exception("POST method unimplemented");
+    }
+
+    function put($url, $headers, $body)
+    {
+        throw new Exception("PUT method unimplemented");
+    }
+
+    function delete($url, $headers)
+    {
+        throw new Exception("DELETE method unimplemented");
+    }
+
+    function userAgent()
+    {
+        return "StatusNet/".STATUSNET_VERSION." (".STATUSNET_CODENAME.")";
+    }
+}
index 9133af7a05ee93345abad7d79935169f92ff5b27..0566701ff16990fbc45b6e3003b6e4f67455c5f7 100644 (file)
@@ -80,14 +80,9 @@ function omb_broadcast_notice($notice)
     $posted = array();
 
     while ($rp->fetch()) {
-        if (!array_key_exists($rp->postnoticeurl, $posted)) {
-            common_log(LOG_DEBUG, 'Posting to ' . $rp->postnoticeurl);
-            if (omb_post_notice_keys($notice, $rp->postnoticeurl, $rp->token, $rp->secret)) {
-                common_log(LOG_DEBUG, 'Finished to ' . $rp->postnoticeurl);
-                $posted[$rp->postnoticeurl] = true;
-            } else {
-                common_log(LOG_DEBUG, 'Failed posting to ' . $rp->postnoticeurl);
-            }
+        if (isset($posted[$rp->postnoticeurl])) {
+            /* We already posted to this url. */
+            continue;
         }
         common_debug('Posting to ' . $rp->postnoticeurl, __FILE__);
 
index 8f13b8852009997165c076c3ba22f4bee1a05e47..2c4d63b0d794df6a1973d7c26dd77c8373576f3f 100644 (file)
@@ -265,12 +265,12 @@ class Router
         $m->connect('api/statuses/:method',
                     array('action' => 'api',
                           'apiaction' => 'statuses'),
-                    array('method' => '(public_timeline|friends_timeline|user_timeline|update|replies|mentions|show|friends|followers|featured)(\.(atom|rss|xml|json))?'));
+                    array('method' => '(public_timeline|home_timeline|friends_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|friends_timeline|replies|mentions|show|destroy|friends|followers)'));
+                    array('method' => '(user_timeline|home_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)'));
 
         // users
 
@@ -429,7 +429,7 @@ class Router
         $m->connect('api/statuses/:method/:argument',
                     array('action' => 'api',
                           'apiaction' => 'statuses'),
-                    array('method' => '(|user_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)'));
+                    array('method' => '(user_timeline|home_timeline|friends_timeline|replies|mentions|show|destroy|friends|followers)'));
 
         $m->connect('api/statusnet/groups/:method/:argument',
                     array('action' => 'api',
index eb450fc5e5e29f73f840649df04419dbf7dd72ec..91bddf381f4f989ee41362eb83fdba083feea173 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /**
- * Laconica, the distributed open-source microblogging tool
+ * StatusNet, the distributed open-source microblogging tool
  *
  * PHP version 5
  *
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  * @category  Plugin
- * @package   Laconica
- * @author    Evan Prodromou <evan@controlyourself.ca>
- * @copyright 2009 Control Yourself, Inc.
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@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://laconi.ca/
+ * @link      http://status.net/
  */
 
-if (!defined('LACONICA')) {
+if (!defined('STATUSNET')) {
     exit(1);
 }
 
@@ -36,10 +36,10 @@ if (!defined('LACONICA')) {
  * and identity system.
  *
  * @category Plugin
- * @package  Laconica
- * @author   Evan Prodromou <evan@controlyourself.ca>
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link     http://laconi.ca/
+ * @link     http://status.net/
  * @link     http://openid.net/
  */
 
index 151b1fb71cdc8111cf7c1a03646b08d65015bc57..d030f2db4dc1f0e31adab283c54105b3bf892f64 100644 (file)
@@ -1,7 +1,7 @@
 /** Howto: create a statusnet theme
  *
  * @package   StatusNet
- * @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @author Sarven Capadisli <csarven@status.net>
  * @copyright 2009 Control Yourself, Inc.
  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  * @link      http://laconi.ca/