Index: trunk/lib/App.inc.php
===================================================================
--- trunk/lib/App.inc.php	(revision 580)
+++ trunk/lib/App.inc.php	(revision 581)
@@ -57,4 +57,7 @@
     public $db;
 
+    // Instance of database session handler object.
+    public $db_session;
+
     // Array of query arguments will be carried persistently between requests.
     protected $_carry_queries = array();
@@ -63,5 +66,5 @@
     protected $_raised_msg_counter = array(MSG_NOTICE => 0, MSG_SUCCESS => 0, MSG_WARNING => 0, MSG_ERR => 0);
 
-    // We're running as CLI. Public becuase we must force this as false when testing sessions via CLI.
+    // We're running as CLI. Public because we must force this as false when testing sessions via CLI.
     public $cli = false;
 
@@ -201,7 +204,4 @@
     public function __construct($namespace='')
     {
-        // Set namespace of application instance.
-        $this->_ns = $namespace;
-
         // Initialize default parameters.
         $this->_params = array_merge($this->_params, $this->_param_defaults);
@@ -227,6 +227,21 @@
     {
         if (self::$instance === null) {
-            // TODO: Yep, having a namespace with one singletone instance is not very useful.
+            // FIXME: Yep, having a namespace with one singleton instance is not very useful. This is a design flaw with the Codebase.
+            // We're currently getting instances of App throughout the codebase using `$app =& App::getInstance();`
+            // with no way to determine what the namespace of the containing application is (e.g., `public` vs. `admin`).
+            // Option 1: provide the project namespace to all classes that use App, and then instantiate with `$app =& App::getInstance($this->_ns);`.
+            // In this case the namespace of the App and the namespace of the auxiliary class must match.
+            // Option 2: may be to clone a specific instance to the "default" instance, so, e.g., `$app =& App::getInstance();`
+            // refers to the same namespace as `$app =& App::getInstance('admin');`
+            // Option 3: is to check if there is only one instance, and return it if an unspecified namespace is requested.
+            // However, in the case when multiple namespaces are in play at the same time, this will fail; unspecified namespaces
+            // would cause the creation of an additional instance, since there would not be an obvious named instance to return.
             self::$instance = new self($namespace);
+        }
+
+        if ('' != $namespace) {
+            // We may not be able to request a specific instance, but we can specify a specific namespace.
+            // We're ignoring all instance requests with a blank namespace, so we use the last given one.
+            self::$instance->_ns = $namespace;
         }
 
@@ -322,4 +337,5 @@
         // Set character set to use for multi-byte string functions.
         mb_internal_encoding($this->getParam('character_set'));
+        ini_set('default_charset', $this->getParam('character_set'));
         switch (mb_strtolower($this->getParam('character_set'))) {
         case 'utf-8' :
@@ -410,5 +426,5 @@
                 // Database session handling.
                 require_once dirname(__FILE__) . '/DBSessionHandler.inc.php';
-                $db_save_handler = new DBSessionHandler($this->db, array(
+                $this->db_session = new DBSessionHandler($this->db, array(
                     'db_table' => 'session_tbl',
                     'create_table' => $this->getParam('db_create_tables'),
@@ -424,5 +440,5 @@
                 $_SESSION['_app'][$this->_ns] = array(
                     'messages' => array(),
-                    'boomerang' => array('url' => array()),
+                    'boomerang' => array(),
                 );
             }
@@ -460,5 +476,5 @@
         if (!$this->cli) {
             if (!headers_sent($h_file, $h_line)) {
-                header('Content-type: text/html; charset=' . $this->getParam('character_set'));
+                header(sprintf('Content-type: text/html; charset=%s', $this->getParam('character_set')));
             } else {
                 $this->logMsg(sprintf('Unable to set Content-type; headers already sent (output started in %s : %s)', $h_file, $h_line), LOG_DEBUG, __FILE__, __LINE__);
@@ -472,7 +488,7 @@
             $codebase_version = trim(file_get_contents($codebase_version_file));
             $this->setParam(array('codebase_version' => $codebase_version));
-            if (!$this->cli) {
+            if (!$this->cli && $this->getParam('codebase_version')) {
                 if (!headers_sent($h_file, $h_line)) {
-                    header('X-Codebase-Version: ' . $codebase_version);
+                    header(sprintf('X-Codebase-Version: %s', $this->getParam('codebase_version')));
                 } else {
                     $this->logMsg(sprintf('Unable to set X-Codebase-Version; headers already sent (output started in %s : %s)', $h_file, $h_line), LOG_DEBUG, __FILE__, __LINE__);
@@ -489,5 +505,5 @@
             if (mb_strpos($site_version_file, '.json') !== false) {
                 $version_json = json_decode(trim(file_get_contents($site_version_file)), true);
-                $site_version = $version_json['version'];
+                $site_version = isset($version_json['version']) ? $version_json['version'] : null;
             } else {
                 $site_version = trim(file_get_contents($site_version_file));
@@ -497,9 +513,12 @@
         if (!$this->cli && $this->getParam('site_version')) {
             if (!headers_sent($h_file, $h_line)) {
-                header('X-Site-Version: ' . $site_version);
+                header(sprintf('X-Site-Version: %s', $this->getParam('site_version')));
             } else {
                 $this->logMsg(sprintf('Unable to set X-Site-Version; headers already sent (output started in %s : %s)', $h_file, $h_line), LOG_DEBUG, __FILE__, __LINE__);
             }
         }
+
+        // Unset environment variables we're done with.
+        unset($_SERVER['DB_SERVER'], $_SERVER['DB_NAME'], $_SERVER['DB_USER'], $_SERVER['DB_PASS'], $_SERVER['SIGNING_KEY']);
 
         $this->running = true;
@@ -1393,6 +1412,4 @@
             return false;
         }
-        // A redirection will never happen immediately after setting the boomerangURL.
-        // Set the time so ensure this doesn't happen. See $app->validBoomerangURL for more.
 
         if ('' != $url && is_string($url)) {
@@ -1401,8 +1418,9 @@
 
             if (isset($_SESSION['_app'][$this->_ns]['boomerang']) && is_array($_SESSION['_app'][$this->_ns]['boomerang']) && !empty($_SESSION['_app'][$this->_ns]['boomerang'])) {
-                // If the ID=>URL pair currently exists in the boomerang array, delete.
+                // If the ID already exists in the boomerang array, delete it.
                 foreach (array_keys($_SESSION['_app'][$this->_ns]['boomerang']) as $existing_id) {
+                    // $existing_id could be null if existing boomerang URL was set without an ID.
                     if ($existing_id === $id) {
-                        $this->logMsg(sprintf('Found and deleting existing ID=>URL pair: %s=>%s', $id, $url), LOG_DEBUG, __FILE__, __LINE__);
+                        $this->logMsg(sprintf('Deleted existing boomerang URL matching ID: %s=>%s', $id, $url), LOG_DEBUG, __FILE__, __LINE__);
                         unset($_SESSION['_app'][$this->_ns]['boomerang'][$existing_id]);
                     }
@@ -1410,4 +1428,6 @@
             }
 
+            // A redirection will never happen immediately after setting the boomerang URL.
+            // Set the time so ensure this doesn't happen. See $app->validBoomerangURL for more.
             if (isset($id)) {
                 $_SESSION['_app'][$this->_ns]['boomerang'][$id] = array(
@@ -1448,5 +1468,5 @@
                 return '';
             }
-        } else if (is_array($_SESSION['_app'][$this->_ns]['boomerang']) && !empty($_SESSION['_app'][$this->_ns]['boomerang'])) {
+        } else if (isset($_SESSION['_app'][$this->_ns]['boomerang']) && is_array($_SESSION['_app'][$this->_ns]['boomerang']) && !empty($_SESSION['_app'][$this->_ns]['boomerang'])) {
             return end($_SESSION['_app'][$this->_ns]['boomerang'])['url'];
         } else {
@@ -1556,12 +1576,10 @@
 
     /**
-     * to enforce the user to connect via http (port 80) by redirecting them to
-     * a http version of the current url.
+     * This function has changed to do nothing. There is no reason to prefer a non-SSL connection, and doing so may result in a redirect loop.
      */
     public function sslOff()
     {
-        if ('' != getenv('HTTPS')) {
-            $this->dieURL('http://' . getenv('HTTP_HOST') . getenv('REQUEST_URI'), null, true);
-        }
+        $app =& App::getInstance();
+        $app->logMsg(sprintf('sslOff was called and ignored.', null), LOG_INFO, __FILE__, __LINE__);
     }
 
