From dcac7ab65281f2ca6017ce5776bd421c9f19bf81 Mon Sep 17 00:00:00 2001
From: Albert Santoni <albert.santoni@sourcefabric.org>
Date: Wed, 18 Feb 2015 12:21:15 -0500
Subject: [PATCH] Fixed a couple of bugs in the new /provisioning/create API

---
 airtime_mvc/application/Bootstrap.php         |  2 +-
 .../application/common/ProvisioningHelper.php | 92 ++++++++++---------
 airtime_mvc/build/sql/defaultdata.sql         |  3 +
 3 files changed, 53 insertions(+), 44 deletions(-)

diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php
index 9fb3dd5c0..bb0954694 100644
--- a/airtime_mvc/application/Bootstrap.php
+++ b/airtime_mvc/application/Bootstrap.php
@@ -35,7 +35,7 @@ require_once (APPLICATION_PATH."/logging/Logging.php");
 Logging::setLogPath('/var/log/airtime/zendphp.log');
 
 // We need to manually route because we can't load Zend without the database being initialized first.
-if (strpos("/provisioning/create", $_SERVER["REDIRECT_URL"]) !== false) {
+if (strpos($_SERVER["REQUEST_URI"], "/provisioning/create") !== false) {
     $provisioningHelper = new ProvisioningHelper($CC_CONFIG["apiKey"][0]);
     $provisioningHelper->createAction();
     die();
diff --git a/airtime_mvc/application/common/ProvisioningHelper.php b/airtime_mvc/application/common/ProvisioningHelper.php
index 58e78b75f..b745b639c 100644
--- a/airtime_mvc/application/common/ProvisioningHelper.php
+++ b/airtime_mvc/application/common/ProvisioningHelper.php
@@ -1,12 +1,8 @@
 <?php
-/**
- * Created by PhpStorm.
- * User: sourcefabric
- * Date: 12/02/15
- * Time: 2:10 PM
- */
 
-class ProvisioningHelper {
+/** This class provides the business logic for station provisioning.  */
+class ProvisioningHelper
+{
 
     /* @var $dbh PDO */
     static $dbh;
@@ -14,18 +10,18 @@ class ProvisioningHelper {
     // Parameter values
     private $dbuser, $dbpass, $dbname, $dbhost, $dbowner, $apikey;
 
-    public function __construct($apikey) {
+    public function __construct($apikey)
+    {
         $this->apikey = $apikey;
     }
 
     /**
      * Endpoint for setting up and installing the Airtime database. This all has to be done without Zend
-     * which is why the code looks so old school (eg. http_response_code).
+     * which is why the code looks so old school (eg. http_response_code). (We can't currently bootstrap our
+     * Zend app without the database unfortunately.)
      */
-    public function createAction() {
-
-        $this->getParams();
-
+    public function createAction()
+    {
         $apikey = $_SERVER['PHP_AUTH_USER'];
         if (!isset($apikey) || $apikey != $this->apikey) {
             Logging::info("Invalid API Key: $apikey");
@@ -35,15 +31,21 @@ class ProvisioningHelper {
         }
 
         try {
-           // $this->setNewDatabaseConnection();
+
+            $this->parsePostParams();
+
+            //For security, the Airtime Pro provisioning system creates the database for the user.
+            // $this->setNewDatabaseConnection();
             //if ($this->checkDatabaseExists()) {
             //    throw new Exception("ERROR: Airtime database already exists");
             //}
             //$this->createDatabase();
+
+            //All we need to do is create the database tables.
             $this->createDatabaseTables();
-        } catch(Exception $e) {
+        } catch (Exception $e) {
             http_response_code(400);
-            Logging::info($e->getMessage());
+            Logging::error($e->getMessage());
             echo $e->getMessage();
             return;
         }
@@ -55,30 +57,33 @@ class ProvisioningHelper {
      * Check if the database settings and credentials given are valid
      * @return boolean true if the database given exists and the user is valid and can access it
      */
-    private function checkDatabaseExists() {
+    private function checkDatabaseExists()
+    {
         $statement = self::$dbh->prepare("SELECT datname FROM pg_database WHERE datname = :dbname");
         $statement->execute(array(":dbname" => $this->dbname));
         $result = $statement->fetch();
         return isset($result[0]);
     }
 
-    private function getParams() {
-        $params = [];
-        parse_str($_SERVER["QUERY_STRING"], $params);
-        foreach ($params as $k => $v) {
-            $this->$k = $v;
-        }
+    private function parsePostParams()
+    {
+        $this->dbuser = $_POST['dbuser'];
+        $this->dbpass = $_POST['dbpass'];
+        $this->dbname = $_POST['dbname'];
+        $this->dbhost = $_POST['dbhost'];
+        $this->dbowner = $_POST['dbowner'];
     }
 
     /**
      * Set up a new database connection based on the parameters in the request
      * @throws PDOException upon failure to connect
      */
-    private function setNewDatabaseConnection() {
+    private function setNewDatabaseConnection()
+    {
         self::$dbh = new PDO("pgsql:host=" . $this->dbhost
-                             . ";dbname=postgres"
-                             . ";port=5432" . ";user=" . $this->dbuser
-                             . ";password=" . $this->dbpass);
+            . ";dbname=postgres"
+            . ";port=5432" . ";user=" . $this->dbuser
+            . ";password=" . $this->dbpass);
         $err = self::$dbh->errorInfo();
         if ($err[1] != null) {
             throw new PDOException("ERROR: Could not connect to database");
@@ -89,11 +94,12 @@ class ProvisioningHelper {
      * Creates the Airtime database using the given credentials
      * @throws Exception
      */
-    private function createDatabase() {
+    private function createDatabase()
+    {
         Logging::info("Creating database...");
         $statement = self::$dbh->prepare("CREATE DATABASE " . pg_escape_string($this->dbname)
-                                         . " WITH ENCODING 'UTF8' TEMPLATE template0"
-                                         . " OWNER " . pg_escape_string($this->dbowner));
+            . " WITH ENCODING 'UTF8' TEMPLATE template0"
+            . " OWNER " . pg_escape_string($this->dbowner));
         if (!$statement->execute()) {
             throw new Exception("ERROR: Failed to create Airtime database");
         }
@@ -103,24 +109,24 @@ class ProvisioningHelper {
      * Install the Airtime database
      * @throws Exception
      */
-    private function createDatabaseTables() {
+    private function createDatabaseTables()
+    {
+        Logging::info("Creating database tables...");
         $sqlDir = dirname(APPLICATION_PATH) . "/build/sql/";
         $files = array("schema.sql", "sequences.sql", "views.sql", "triggers.sql", "defaultdata.sql");
         foreach ($files as $f) {
-            try {
-                /*
-                 * Unfortunately, we need to use exec here due to PDO's lack of support for importing
-                 * multi-line .sql files. PDO->exec() almost works, but any SQL errors stop the import,
-                 * so the necessary DROPs on non-existent tables make it unusable. Prepared statements
-                 * have multiple issues; they similarly die on any SQL errors, fail to read in multi-line
-                 * commands, and fail on any unescaped ? or $ characters.
-                 */
-                exec("export PGPASSWORD=" . $this->dbpass . " && psql -U " . $this->dbuser . " --dbname "
-                     . $this->dbname . " -h " . $this->dbhost . " -f $sqlDir$f 2>/dev/null", $out, $status);
-            } catch (Exception $e) {
+            /*
+             * Unfortunately, we need to use exec here due to PDO's lack of support for importing
+             * multi-line .sql files. PDO->exec() almost works, but any SQL errors stop the import,
+             * so the necessary DROPs on non-existent tables make it unusable. Prepared statements
+             * have multiple issues; they similarly die on any SQL errors, fail to read in multi-line
+             * commands, and fail on any unescaped ? or $ characters.
+             */
+            exec("PGPASSWORD=$this->dbpass psql -U $this->dbuser --dbname $this->dbname -h $this->dbhost -f $sqlDir$f", $out, $status);
+            if ($status != 0) {
                 throw new Exception("ERROR: Failed to create database tables");
             }
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/airtime_mvc/build/sql/defaultdata.sql b/airtime_mvc/build/sql/defaultdata.sql
index af82be2b8..3c1a60752 100644
--- a/airtime_mvc/build/sql/defaultdata.sql
+++ b/airtime_mvc/build/sql/defaultdata.sql
@@ -1,3 +1,6 @@
+-- Schema version
+INSERT INTO cc_pref("keystr", "valstr") VALUES('system_version', '2.5.9');
+
 INSERT INTO cc_subjs ("login", "type", "pass") VALUES ('admin', 'A', md5('admin'));
 -- added in 2.3
 INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('off_air_meta', 'Airtime - offline', 'string');