]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
First pass at complete global API
authorEvan Prodromou <evan@status.net>
Fri, 10 Jun 2011 19:51:30 +0000 (15:51 -0400)
committerEvan Prodromou <evan@status.net>
Fri, 10 Jun 2011 19:51:30 +0000 (15:51 -0400)
plugins/DomainStatusNetwork/DomainStatusNetworkPlugin.php
plugins/DomainStatusNetwork/actions/globallogin.php
plugins/DomainStatusNetwork/actions/globalrecover.php [new file with mode: 0644]
plugins/DomainStatusNetwork/actions/globalregister.php
plugins/DomainStatusNetwork/domainstatusnetworkinstaller.php [deleted file]
plugins/DomainStatusNetwork/lib/domainstatusnetworkinstaller.php [new file with mode: 0644]
plugins/DomainStatusNetwork/lib/globalapiaction.php [new file with mode: 0644]

index 876443aa3fb4118d1460ce909858115b045af615..efb1aae4d8c9929b41f529b2c900de256713c865 100644 (file)
@@ -97,8 +97,16 @@ class DomainStatusNetworkPlugin extends Plugin
 
         switch ($cls)
         {
+        case 'GlobalregisterAction':
+        case 'GloballoginAction':
+        case 'GlobalrecoverAction':
+            include_once $dir . '/actions/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
+            return false;
         case 'DomainStatusNetworkInstaller':
-            include_once $dir . '/' . strtolower($cls) . '.php';
+            include_once $dir . '/lib/' . strtolower($cls) . '.php';
+            return false;
+        case 'GlobalApiAction':
+            include_once $dir . '/lib/' . strtolower($cls) . '.php';
             return false;
         default:
             return true;
@@ -138,6 +146,17 @@ class DomainStatusNetworkPlugin extends Plugin
         return true;
     }
 
+    function onRouterInitialized($m)
+    {
+        if (common_config('globalapi', 'enabled')) {
+            foreach (array('register', 'login', 'recover') as $method) {
+                $m->connect('api/statusnet/global/'.$method,
+                            array('action' => 'global'.$method));
+            }
+        }
+        return true;
+    }
+
     static function nicknameForDomain($domain)
     {
         $registered = self::registeredDomain($domain);
@@ -261,12 +280,16 @@ class DomainStatusNetworkPlugin extends Plugin
         $loginToken = Login_token::makeNew($user);
 
         if (empty($loginToken)) {
-            throw new ServerException(_('Cannot log in.'));
+            throw new ServerException(sprintf(_('Could not create new login token for user %s'), $user->nickname));
         }
 
         $url = common_local_url('otp', array('user_id' => $loginToken->user_id,
                                              'token' => $loginToken->token));
 
+        if (empty($url)) {
+            throw new ServerException(sprintf(_('Could not create new OTP URL for user %s'), $user->nickname));
+        }
+
         return $url;
     }
 
@@ -282,6 +305,12 @@ class DomainStatusNetworkPlugin extends Plugin
 
         StatusNet::switchSite($sn->nickname);
 
+        $user = User::staticGet('email', $email);
+        
+        if (empty($user)) {
+            throw new ClientException(_('No such user.'));
+        }
+    }
 }
 
 // The way addPlugin() works, this global variable gets disappeared.
index 034d719a2f4677052cbd96492212b82d53980688..f843392f44af95ec4c09373f1ea8c9d4d606c3b5 100644 (file)
@@ -35,7 +35,7 @@ if (!defined('STATUSNET')) {
 }
 
 /**
- * Class comment
+ * Login to a site
  *
  * @category  Action
  * @package   StatusNet
@@ -45,8 +45,10 @@ if (!defined('STATUSNET')) {
  * @link      http://status.net/
  */
 
-class GlobalLoginAction extends Action
+class GloballoginAction extends GlobalApiAction
 {
+    var $password;
+
     /**
      * For initializing members of the class.
      *
@@ -58,6 +60,15 @@ class GlobalLoginAction extends Action
     function prepare($argarray)
     {
         parent::prepare($argarray);
+
+        $password = $this->trimmed('password');
+
+        if (empty($password)) {
+            throw new ClientException(_('No password.'));
+        }
+
+        $this->password = $password;
+
         return true;
     }
 
@@ -71,6 +82,15 @@ class GlobalLoginAction extends Action
 
     function handle($argarray=null)
     {
+        try {
+            $url = DomainStatusNetworkPlugin::login($email, $password);
+            $this->showSuccess(array('url' => $url));
+        } catch (ClientException $ce) {
+            $this->showError($ce->getMessage());
+        } catch (Exception $e) {
+            common_log(LOG_ERR, $e->getMessage());
+            $this->showError(_('An internal error occurred.'));
+        }
         return;
     }
 }
diff --git a/plugins/DomainStatusNetwork/actions/globalrecover.php b/plugins/DomainStatusNetwork/actions/globalrecover.php
new file mode 100644 (file)
index 0000000..9b688cb
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Recover a password
+ * 
+ * PHP version 5
+ *
+ * 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  DomainStatusNetwork
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Recover a password
+ *
+ * @category  Action
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class GlobalrecoverAction extends GlobalApiAction
+{
+    /**
+     * For initializing members of the class.
+     *
+     * @param array $argarray misc. arguments
+     *
+     * @return boolean true
+     */
+
+    function prepare($argarray)
+    {
+        parent::prepare($argarray);
+        return true;
+    }
+
+    /**
+     * Handler method
+     *
+     * @param array $argarray is ignored since it's now passed in in prepare()
+     *
+     * @return void
+     */
+
+    function handle($argarray=null)
+    {
+        try {
+            DomainStatusNetworkPlugin::recoverPassword($email);
+            $this->showSuccess();
+        } catch (ClientException $ce) {
+            $this->showError($ce->getMessage());
+        } catch (Exception $e) {
+            common_log(LOG_ERR, $e->getMessage());
+            $this->showError(_('An internal error occurred.'));
+        }
+        return;
+    }
+}
index ad223808ff39b501227996699502d6caca11dced..42dd207f4eb3f43de937993028deb1d9b40bb41f 100644 (file)
@@ -35,7 +35,7 @@ if (!defined('STATUSNET')) {
 }
 
 /**
- * Class comment
+ * An action to globally register a new user
  *
  * @category  Action
  * @package   StatusNet
@@ -45,7 +45,7 @@ if (!defined('STATUSNET')) {
  * @link      http://status.net/
  */
 
-class GlobalRegisterAction extends Action
+class GlobalregisterAction extends GlobalApiAction
 {
     /**
      * For initializing members of the class.
@@ -71,48 +71,16 @@ class GlobalRegisterAction extends Action
 
     function handle($argarray=null)
     {
-        return;
-    }
+        try {
+            DomainStatusNetworkPlugin::registerEmail($this->email, true);
+            $this->showSuccess();
+        } catch (ClientException $e) {
+            $this->showError($e->getMessage());
+        } catch (Exception $e) {
+            common_log(LOG_ERR, $e->getMessage());
+            $this->showError(_('An internal error occurred.'));
+        }
 
-    /**
-     * Return true if read only.
-     *
-     * MAY override
-     *
-     * @param array $args other arguments
-     *
-     * @return boolean is read only action?
-     */
-
-    function isReadOnly($args)
-    {
-        return false;
-    }
-
-    /**
-     * Return last modified, if applicable.
-     *
-     * MAY override
-     *
-     * @return string last modified http header
-     */
-    function lastModified()
-    {
-        // For comparison with If-Last-Modified
-        // If not applicable, return null
-        return null;
-    }
-
-    /**
-     * Return etag, if applicable.
-     *
-     * MAY override
-     *
-     * @return string etag http header
-     */
-
-    function etag()
-    {
-        return null;
+        return;
     }
 }
diff --git a/plugins/DomainStatusNetwork/domainstatusnetworkinstaller.php b/plugins/DomainStatusNetwork/domainstatusnetworkinstaller.php
deleted file mode 100644 (file)
index b2042ab..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-<?php
-/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2011, StatusNet, Inc.
- *
- * Installer class for domain-based multi-homing systems
- *
- * PHP version 5
- *
- * 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  DomainStatusNetwork
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2011 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET')) {
-    // This check helps protect against security problems;
-    // your code file can't be executed directly from the web.
-    exit(1);
-}
-
-/**
- * Installer class for domain-based multi-homing systems
- *
- * @category  DomainStatusNetwork
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2011 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-class DomainStatusNetworkInstaller extends Installer
-{
-    protected $domain   = null;
-    protected $rootname = null;
-    protected $sitedb   = null;
-    protected $rootpass = null;
-    protected $nickname = null;
-    protected $sn       = null;
-
-    public $verbose     = false;
-
-    function __construct($domain)
-    {
-        $this->domain = $domain;
-    }
-
-    /**
-     * Go for it!
-     * @return boolean success
-     */
-    function main()
-    {
-        // We don't check prereqs. Check 'em before setting up a
-        // multi-home system, kthxbi
-        if ($this->prepare()) {
-            return $this->handle();
-        } else {
-            $this->showHelp();
-            return false;
-        }
-    }
-
-    /**
-     * Get our input parameters...
-     * @return boolean success
-     */
-    function prepare()
-    {
-        $config = $this->getConfig();
-
-        $this->nickname = DomainStatusNetworkPlugin::nicknameForDomain($this->domain);
-
-        // XXX make this configurable
-
-        $this->sitename = sprintf('The %s Status Network', $this->domain);
-
-        $this->server   = $this->nickname.'.'.$config['WILDCARD'];
-        $this->path     = null;
-        $this->fancy    = true;
-
-        $datanick = $this->databaseize($this->nickname);
-
-        $this->host     = $config['DBHOSTNAME'];
-        $this->database = $datanick.$config['DBBASE'];
-        $this->dbtype   = 'mysql'; // XXX: support others... someday
-        $this->username = $datanick.$config['USERBASE'];
-
-        // Max size for MySQL
-
-        if (strlen($this->username) > 16) {
-            $this->username = sprintf('%s%08x', substr($this->username, 0, 8), crc32($this->username));
-        }
-
-        $pwgen = $config['PWDGEN'];
-
-        $password = `$pwgen`;
-
-        $this->password = trim($password);
-
-        // For setting up the database
-
-        $this->rootname = $config['ADMIN'];
-        $this->rootpass = $config['ADMINPASS'];
-        $this->sitehost = $config['DBHOST'];
-        $this->sitedb   = $config['SITEDB'];
-
-        // Explicitly empty
-
-        $this->adminNick    = null;
-        $this->adminPass    = null;
-        $this->adminEmail   = null;
-        $this->adminUpdates = null;
-
-        /** Should we skip writing the configuration file? */
-        $this->skipConfig = true;
-
-        if (!$this->validateDb()) {
-            return false;
-        }
-
-        return true;
-    }
-
-    function handle()
-    {
-        return $this->doInstall();
-    }
-
-    function setupDatabase()
-    {
-        $this->updateStatus('Creating database...');
-        $this->createDatabase();
-        parent::setupDatabase();
-        $this->updateStatus('Creating file directories...');
-        $this->createDirectories();
-        $this->updateStatus('Saving status network...');
-        $this->saveStatusNetwork();
-        $this->updateStatus('Checking schema for plugins...');
-        $this->checkSchema();
-    }
-
-    function saveStatusNetwork()
-    {
-        Status_network::setupDB($this->sitehost,
-                                $this->rootname,
-                                $this->rootpass,
-                                $this->sitedb, array());
-
-        $sn = new Status_network();
-
-        $sn->nickname = $this->nickname;
-        $sn->dbhost   = $this->host;
-        $sn->dbuser   = $this->username;
-        $sn->dbpass   = $this->password;
-        $sn->dbname   = $this->database;
-        $sn->sitename = $this->sitename;
-
-        $result = $sn->insert();
-
-        if (!$result) {
-            throw new ServerException("Could not create status_network: " . print_r($sn, true));
-        }
-
-        // Re-fetch; stupid auto-increment integer isn't working
-
-        $sn = Status_network::staticGet('nickname', $sn->nickname);
-
-        if (empty($sn)) {
-            throw new ServerException("Created {$this->nickname} status_network and could not find it again.");
-        }
-
-        $sn->setTags(array('domain='.$this->domain));
-
-        $this->sn = $sn;
-    }
-
-    function checkSchema()
-    {
-        $config = $this->getConfig();
-
-        Status_network::$wildcard = $config['WILDCARD'];
-
-        StatusNet::switchSite($this->nickname);
-
-        Event::handle('CheckSchema');
-    }
-
-    function getStatusNetwork()
-    {
-        return $this->sn;
-    }
-
-    function createDirectories()
-    {
-        $config = $this->getConfig();
-
-        foreach (array('AVATARBASE', 'BACKGROUNDBASE', 'FILEBASE') as $key) {
-            $base = $config[$key];
-            $dirname = $base.'/'.$this->nickname;
-
-            // Make sure our bits are set
-            $mask = umask(0);
-            mkdir($dirname, 0770, true);
-            umask($mask);
-
-            // If you set the setuid bit on your base dirs this should be
-            // unnecessary, but just in case. You must be root for this
-            // to work.
-
-            if (array_key_exists('WEBUSER', $config)) {
-                chown($dirname, $config['WEBUSER']);
-            }
-            if (array_key_exists('WEBGROUP', $config)) {
-                chgrp($dirname, $config['WEBGROUP']);
-            }
-        }
-    }
-
-    function createDatabase()
-    {
-        // Create the New DB
-        $res = mysql_connect($this->host, $this->rootname, $this->rootpass);
-        if (!$res) {
-            throw new ServerException("Cannot connect to {$this->host} as {$this->rootname}.");
-        }
-
-        mysql_query("CREATE DATABASE ". mysql_real_escape_string($this->database), $res);
-
-        $return = mysql_select_db($this->database, $res);
-
-        if (!$return) {
-            throw new ServerException("Unable to connect to {$this->database} on {$this->host}.");
-        }
-
-        foreach (array('localhost', '%') as $src) {
-            mysql_query("GRANT ALL ON " .
-                        mysql_real_escape_string($this->database).".* TO '" .
-                        $this->username . "'@'".$src."' ".
-                        "IDENTIFIED BY '".$this->password."'", $res);
-        }
-
-        mysql_close($res);
-    }
-
-    function getConfig()
-    {
-        static $config;
-
-        $cfg_file = "/etc/statusnet/setup.cfg";
-
-        if (empty($config)) {
-            $result = parse_ini_file($cfg_file);
-
-            $config = array();
-            foreach ($result as $key => $value) {
-                $key = str_replace('export ', '', $key);
-                $config[$key] = $value;
-            }
-        }
-
-        return $config;
-    }
-
-    function showHelp()
-    {
-    }
-
-    function warning($message, $submessage='')
-    {
-        print $this->html2text($message) . "\n";
-        if ($submessage != '') {
-            print "  " . $this->html2text($submessage) . "\n";
-        }
-        print "\n";
-    }
-
-    function updateStatus($status, $error=false)
-    {
-        if ($this->verbose || $error) {
-            if ($error) {
-                print "ERROR: ";
-            }
-            print $this->html2text($status);
-            print "\n";
-        }
-    }
-
-    private function html2text($html)
-    {
-        // break out any links for text legibility
-        $breakout = preg_replace('/<a[^>+]\bhref="(.*)"[^>]*>(.*)<\/a>/',
-                                 '\2 &lt;\1&gt;',
-                                 $html);
-        return html_entity_decode(strip_tags($breakout), ENT_QUOTES, 'UTF-8');
-    }
-
-    function databaseize($nickname)
-    {
-        $nickname = str_replace('-', '_', $nickname);
-        return $nickname;
-    }
-}
diff --git a/plugins/DomainStatusNetwork/lib/domainstatusnetworkinstaller.php b/plugins/DomainStatusNetwork/lib/domainstatusnetworkinstaller.php
new file mode 100644 (file)
index 0000000..b2042ab
--- /dev/null
@@ -0,0 +1,318 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Installer class for domain-based multi-homing systems
+ *
+ * PHP version 5
+ *
+ * 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  DomainStatusNetwork
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Installer class for domain-based multi-homing systems
+ *
+ * @category  DomainStatusNetwork
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+class DomainStatusNetworkInstaller extends Installer
+{
+    protected $domain   = null;
+    protected $rootname = null;
+    protected $sitedb   = null;
+    protected $rootpass = null;
+    protected $nickname = null;
+    protected $sn       = null;
+
+    public $verbose     = false;
+
+    function __construct($domain)
+    {
+        $this->domain = $domain;
+    }
+
+    /**
+     * Go for it!
+     * @return boolean success
+     */
+    function main()
+    {
+        // We don't check prereqs. Check 'em before setting up a
+        // multi-home system, kthxbi
+        if ($this->prepare()) {
+            return $this->handle();
+        } else {
+            $this->showHelp();
+            return false;
+        }
+    }
+
+    /**
+     * Get our input parameters...
+     * @return boolean success
+     */
+    function prepare()
+    {
+        $config = $this->getConfig();
+
+        $this->nickname = DomainStatusNetworkPlugin::nicknameForDomain($this->domain);
+
+        // XXX make this configurable
+
+        $this->sitename = sprintf('The %s Status Network', $this->domain);
+
+        $this->server   = $this->nickname.'.'.$config['WILDCARD'];
+        $this->path     = null;
+        $this->fancy    = true;
+
+        $datanick = $this->databaseize($this->nickname);
+
+        $this->host     = $config['DBHOSTNAME'];
+        $this->database = $datanick.$config['DBBASE'];
+        $this->dbtype   = 'mysql'; // XXX: support others... someday
+        $this->username = $datanick.$config['USERBASE'];
+
+        // Max size for MySQL
+
+        if (strlen($this->username) > 16) {
+            $this->username = sprintf('%s%08x', substr($this->username, 0, 8), crc32($this->username));
+        }
+
+        $pwgen = $config['PWDGEN'];
+
+        $password = `$pwgen`;
+
+        $this->password = trim($password);
+
+        // For setting up the database
+
+        $this->rootname = $config['ADMIN'];
+        $this->rootpass = $config['ADMINPASS'];
+        $this->sitehost = $config['DBHOST'];
+        $this->sitedb   = $config['SITEDB'];
+
+        // Explicitly empty
+
+        $this->adminNick    = null;
+        $this->adminPass    = null;
+        $this->adminEmail   = null;
+        $this->adminUpdates = null;
+
+        /** Should we skip writing the configuration file? */
+        $this->skipConfig = true;
+
+        if (!$this->validateDb()) {
+            return false;
+        }
+
+        return true;
+    }
+
+    function handle()
+    {
+        return $this->doInstall();
+    }
+
+    function setupDatabase()
+    {
+        $this->updateStatus('Creating database...');
+        $this->createDatabase();
+        parent::setupDatabase();
+        $this->updateStatus('Creating file directories...');
+        $this->createDirectories();
+        $this->updateStatus('Saving status network...');
+        $this->saveStatusNetwork();
+        $this->updateStatus('Checking schema for plugins...');
+        $this->checkSchema();
+    }
+
+    function saveStatusNetwork()
+    {
+        Status_network::setupDB($this->sitehost,
+                                $this->rootname,
+                                $this->rootpass,
+                                $this->sitedb, array());
+
+        $sn = new Status_network();
+
+        $sn->nickname = $this->nickname;
+        $sn->dbhost   = $this->host;
+        $sn->dbuser   = $this->username;
+        $sn->dbpass   = $this->password;
+        $sn->dbname   = $this->database;
+        $sn->sitename = $this->sitename;
+
+        $result = $sn->insert();
+
+        if (!$result) {
+            throw new ServerException("Could not create status_network: " . print_r($sn, true));
+        }
+
+        // Re-fetch; stupid auto-increment integer isn't working
+
+        $sn = Status_network::staticGet('nickname', $sn->nickname);
+
+        if (empty($sn)) {
+            throw new ServerException("Created {$this->nickname} status_network and could not find it again.");
+        }
+
+        $sn->setTags(array('domain='.$this->domain));
+
+        $this->sn = $sn;
+    }
+
+    function checkSchema()
+    {
+        $config = $this->getConfig();
+
+        Status_network::$wildcard = $config['WILDCARD'];
+
+        StatusNet::switchSite($this->nickname);
+
+        Event::handle('CheckSchema');
+    }
+
+    function getStatusNetwork()
+    {
+        return $this->sn;
+    }
+
+    function createDirectories()
+    {
+        $config = $this->getConfig();
+
+        foreach (array('AVATARBASE', 'BACKGROUNDBASE', 'FILEBASE') as $key) {
+            $base = $config[$key];
+            $dirname = $base.'/'.$this->nickname;
+
+            // Make sure our bits are set
+            $mask = umask(0);
+            mkdir($dirname, 0770, true);
+            umask($mask);
+
+            // If you set the setuid bit on your base dirs this should be
+            // unnecessary, but just in case. You must be root for this
+            // to work.
+
+            if (array_key_exists('WEBUSER', $config)) {
+                chown($dirname, $config['WEBUSER']);
+            }
+            if (array_key_exists('WEBGROUP', $config)) {
+                chgrp($dirname, $config['WEBGROUP']);
+            }
+        }
+    }
+
+    function createDatabase()
+    {
+        // Create the New DB
+        $res = mysql_connect($this->host, $this->rootname, $this->rootpass);
+        if (!$res) {
+            throw new ServerException("Cannot connect to {$this->host} as {$this->rootname}.");
+        }
+
+        mysql_query("CREATE DATABASE ". mysql_real_escape_string($this->database), $res);
+
+        $return = mysql_select_db($this->database, $res);
+
+        if (!$return) {
+            throw new ServerException("Unable to connect to {$this->database} on {$this->host}.");
+        }
+
+        foreach (array('localhost', '%') as $src) {
+            mysql_query("GRANT ALL ON " .
+                        mysql_real_escape_string($this->database).".* TO '" .
+                        $this->username . "'@'".$src."' ".
+                        "IDENTIFIED BY '".$this->password."'", $res);
+        }
+
+        mysql_close($res);
+    }
+
+    function getConfig()
+    {
+        static $config;
+
+        $cfg_file = "/etc/statusnet/setup.cfg";
+
+        if (empty($config)) {
+            $result = parse_ini_file($cfg_file);
+
+            $config = array();
+            foreach ($result as $key => $value) {
+                $key = str_replace('export ', '', $key);
+                $config[$key] = $value;
+            }
+        }
+
+        return $config;
+    }
+
+    function showHelp()
+    {
+    }
+
+    function warning($message, $submessage='')
+    {
+        print $this->html2text($message) . "\n";
+        if ($submessage != '') {
+            print "  " . $this->html2text($submessage) . "\n";
+        }
+        print "\n";
+    }
+
+    function updateStatus($status, $error=false)
+    {
+        if ($this->verbose || $error) {
+            if ($error) {
+                print "ERROR: ";
+            }
+            print $this->html2text($status);
+            print "\n";
+        }
+    }
+
+    private function html2text($html)
+    {
+        // break out any links for text legibility
+        $breakout = preg_replace('/<a[^>+]\bhref="(.*)"[^>]*>(.*)<\/a>/',
+                                 '\2 &lt;\1&gt;',
+                                 $html);
+        return html_entity_decode(strip_tags($breakout), ENT_QUOTES, 'UTF-8');
+    }
+
+    function databaseize($nickname)
+    {
+        $nickname = str_replace('-', '_', $nickname);
+        return $nickname;
+    }
+}
diff --git a/plugins/DomainStatusNetwork/lib/globalapiaction.php b/plugins/DomainStatusNetwork/lib/globalapiaction.php
new file mode 100644 (file)
index 0000000..ef77d89
--- /dev/null
@@ -0,0 +1,118 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * An action that requires an API key
+ * 
+ * PHP version 5
+ *
+ * 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  DomainStatusNetwork
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * An action that requires an API key
+ *
+ * @category  General
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class GlobalApiAction extends Action
+{
+    var $email;
+
+    /**
+     * Check for an API key, and throw an exception if it's not set
+     *
+     * @param array $args URL and POST params
+     *
+     * @return boolean continuation flag
+     */
+
+    function prepare($args)
+    {
+        StatusNet::setApi(true); // reduce exception reports to aid in debugging
+
+        parent::prepare($args);
+
+        if (!common_config('globalapi', 'enabled')) {
+            throw new ClientException(_('Global API not enabled.'));
+        }
+
+        $apikey = $this->trimmed('apikey');
+
+        if (empty($apikey)) {
+            throw new ClientException(_('No API key.'));
+        }
+
+        $expected = common_config('globalapi', 'key');
+
+        if ($expected != $apikey) {
+            // FIXME: increment a counter by IP address to prevent brute-force
+            // attacks on the key.
+            throw new ClientException(_('Bad API key.'));
+        }
+
+        $email = common_canonical_email($this->trimmed('email'));
+
+        if (empty($email)) {
+            throw new ClientException(_('No email address.'));
+        }
+
+        if (!Validate::email($email, common_config('email', 'check_domain'))) {
+            throw new ClientException(_('Invalid email address.'));
+        }
+
+        $this->email = $email;
+
+        return true;
+    }
+
+    function showError($message)
+    {
+        $this->showOutput(array('error' => $message));
+    }
+
+    function showSuccess($values=null)
+    {
+        if (empty($values)) {
+            $values = array();
+        }
+        $values['success'] = 1;
+        $this->showOutput($values);
+    }
+
+    function showOutput($values)
+    {
+        header('Content-Type: application/json; charset=utf-8');
+        print(json_encode($values));
+    }
+}