Index: trunk/lib/App.inc.php
===================================================================
--- trunk/lib/App.inc.php	(revision 685)
+++ trunk/lib/App.inc.php	(revision 686)
@@ -486,5 +486,5 @@
 
         // To get a safe hostname, remove port and invalid hostname characters.
-        $safe_http_host = preg_replace('/[^a-z\d.:-]/', '', strtok(getenv('HTTP_HOST'), ':'));
+        $safe_http_host = preg_replace('/[^a-z\d.:-]/', '', strtok(getenv('HTTP_HOST'), ':')); // FIXME: strtok shouldn't be used if there is a chance HTTP_HOST may be empty except for the port, e.g., `:80` will return `80`
         // If strtok() matched a ':' in the previous line, the rest of the string contains the port number (or FALSE)
         $safe_http_port = preg_replace('/[^0-9]/', '', strtok(''));
@@ -1118,7 +1118,7 @@
         }
 
-        // If the URL is empty, use REQUEST_URI without the QUERY_STRING.
+        // If the URL is empty, use REQUEST_URI stripped of its query string.
         if ('' == $url) {
-            $url = str_replace([getenv('QUERY_STRING'), '?'], '', getenv('REQUEST_URI'));
+            $url = (strstr(getenv('REQUEST_URI'), '?', true) ?: getenv('REQUEST_URI')); // strstr() returns false if '?' is not found, so use a shorthand ternary operator.
         }
 
@@ -1208,16 +1208,14 @@
     }
 
-    /**
-     * Prints a hidden form element with the PHPSESSID when cookies are not used, as well
-     * as hidden form elements for GET_VARS that might be in use.
-     *
-     * @param  mixed  $carry_args        Additional url arguments to carry in the query,
-     *                                   or FALSE to prevent carrying queries. Can be any of the following formats:
-     *                                      array('key1', key2', key3')  <-- to save these keys if in the form data.
-     *                                      array('key1'=>'value', key2'='value')  <-- to set keys to default values if not present in form data.
-     *                                      false  <-- To not carry any queries. If URL already has queries those will be retained.
-     * @param   bool    $include_csrf_token     Set to true to include the csrf_token in the form. Only use this for forms with action="post" to prevent the token from being revealed in the URL.
-     */
-    public function printHiddenSession($carry_args=null, $include_csrf_token=false)
+    /*
+    * Returns a string containing <input type="hidden" > for session, carried queries, and CSRF token.
+    *
+    * @access   public
+    * @param    (see printHiddenSession)
+    * @return   string
+    * @author   Quinn Comendant <quinn@strangecode.com>
+    * @since    25 May 2019 15:01:40
+    */
+    public function getHiddenSession($carry_args=null, $include_csrf_token=false)
     {
         if (!$this->running) {
@@ -1225,4 +1223,6 @@
             return false;
         }
+
+        $out = '';
 
         // Get any provided query arguments to include in the final hidden form data.
@@ -1260,9 +1260,9 @@
                     foreach ($val as $subval) {
                         if ('' != $key && '' != $subval) {
-                            printf('<input type="hidden" name="%s[]" value="%s" />', $key, $subval);
+                            $out .= sprintf('<input type="hidden" name="%s[]" value="%s" />', $key, $subval);
                         }
                     }
                 } else if ('' != $key && '' != $val) {
-                    printf('<input type="hidden" name="%s" value="%s" />', $key, $val);
+                    $out .= sprintf('<input type="hidden" name="%s" value="%s" />', $key, $val);
                 }
             }
@@ -1280,5 +1280,5 @@
         && $this->getParam('session_use_trans_sid')
         ) {
-            printf('<input type="hidden" name="%s" value="%s" />', session_name(), session_id());
+            $out .= sprintf('<input type="hidden" name="%s" value="%s" />', session_name(), session_id());
         }
 
@@ -1286,6 +1286,24 @@
         // This token can be validated upon form submission with $app->verifyCSRFToken() or $app->requireValidCSRFToken()
         if ($this->getParam('csrf_token_enabled') && $include_csrf_token) {
-            printf('<input type="hidden" name="%s" value="%s" />', $this->getParam('csrf_token_name'), $this->getCSRFToken());
-        }
+            $out .= sprintf('<input type="hidden" name="%s" value="%s" />', $this->getParam('csrf_token_name'), $this->getCSRFToken());
+        }
+
+        return $out;
+    }
+
+    /**
+     * Prints a hidden form element with the PHPSESSID when cookies are not used, as well
+     * as hidden form elements for GET_VARS that might be in use.
+     *
+     * @param  mixed  $carry_args        Additional url arguments to carry in the query,
+     *                                   or FALSE to prevent carrying queries. Can be any of the following formats:
+     *                                      array('key1', key2', key3')  <-- to save these keys if in the form data.
+     *                                      array('key1'=>'value', key2'='value')  <-- to set keys to default values if not present in form data.
+     *                                      false  <-- To not carry any queries. If URL already has queries those will be retained.
+     * @param   bool    $include_csrf_token     Set to true to include the csrf_token in the form. Only use this for forms with action="post" to prevent the token from being revealed in the URL.
+     */
+    public function printHiddenSession($carry_args=null, $include_csrf_token=false)
+    {
+        echo $this->getHiddenSession($carry_args, $include_csrf_token);
     }
 
Index: trunk/lib/Navigation.inc.php
===================================================================
--- trunk/lib/Navigation.inc.php	(revision 685)
+++ trunk/lib/Navigation.inc.php	(revision 686)
@@ -440,6 +440,6 @@
         }
 
-        $actual_uri = $include_query ? $_SERVER['REQUEST_URI'] : strtok($_SERVER['REQUEST_URI'], '?');
-        $test_uri = $include_query ? $test_uri : strtok($test_uri, '?');
+        $actual_uri = $include_query ? $_SERVER['REQUEST_URI'] : (strstr(getenv('REQUEST_URI'), '?', true) ?: getenv('REQUEST_URI')); // strstr() returns false if '?' is not found, so use a shorthand ternary operator.
+        $test_uri = $include_query ? $test_uri : (strstr($test_uri, '?', true) ?: $test_uri); // strstr() returns false if '?' is not found, so use a shorthand ternary operator.
         if (mb_strtolower($test_uri) == mb_strtolower($actual_uri)) {
             // $app->logMsg(sprintf('Current page (%s) == test URI (%s)', $actual_uri, $test_uri), LOG_DEBUG, __FILE__, __LINE__);
