PHP version 4.3.2 with register_globals OFF in Linux Red Hat 7.3
Very first lines of index.php:
session_start(); // USED FOR ANY STORED SESSION VARIABLES (ONLY HAS TO BE SET HERE)
echo "PHPSESSID = $PHPSESSID<P>";
echo "SESSION the moment you first enter this script of $PHP_SELF is: "; print_r(array_keys($_SESSION)); echo'<P>';
This is what you see the moment you first go into index.php and have not yet submitted a search query:
PHPSESSID = a964d0d6683757cafbe5576737ea5bf9
SESSION the moment you first enter this script of /image_catalog/index.php is: Array ( [0] => search [1] => sql )
Ok, now you submitted a search query. You entered some form stuff and submitted. You're now at the search results page (which is also "index.php"); this is what you see:
PHPSESSID = a964d0d6683757cafbe5576737ea5bf9
SESSION the moment you first enter this script of /image_catalog/index.php is: Array ( [0] => search [1] => sql )
GET: Array ( )
POST: Array ( [0] => image_name [1] => allAlbums [2] => album [3] => boolword [4] => keywords [5] => persons [6] => events [7] => image_alt [8] => image_creation_start_month [9] => image_creation_start_day [10] => image_creation_start_year [11] => image_creation_end_month [12] => image_creation_end_day [13] => image_creation_end_year [14] => image_location_city [15] => image_location_state [16] => image_location_country [17] => sortBy [18] => search [19] => isFromSearch [20] => section )
SESSION: Array ( [0] => search [1] => sql )
PHPSESSID = a964d0d6683757cafbe5576737ea5bf9
SESSION after setting it is: Array ( [0] => search [1] => sql [2] => hidden )
(note: to save space and sensitive info I am not doing:
print_r($_POST);
but instead I'm using
print_r(array_keys($_POST));
, and the same with $_GET)
$_SESSION['sql'] is set via an instance of SearchPerformer object that runs the generateSearchSQL() method:
class SearchPerformer extends DBActionPerformer {
function SearchPerformer () { // CONSTRUCTOR
$this->doSearch(); // THIS METHOD RUNS generateSearchSQL()
}
function &displayResults() { // STATIC HTML STRING METHOD
$html = SearchView::retainFormElements($html); // SEE BELOW FOR CODE DETAIL
// DO MORE STUFF TO $html
return $html;
}
function generateSearchSQL() { // SQL STRING METHOD
// BUILD $sql HERE WITH STUFF
$_SESSION['sql'] = $sql;
// DO MORE STUFF
return $sql;
}
}
$performer =& new SearchPerformer(); // CONSTRUCTOR
So everything is fine so far; I have $SESSION['sql'] and I even have $SESSION['hidden'] which is set via the displayResults() method in the SearchPerformer object, it running this class method (class SearchView is NOT instantiated here!!!):
class SearchView extends View {
function SearchView() {} // CONSTRUCTOR (you will be instantiating SearchView objects elsewhere, just not in SearchPerformer's methods)
function &retainFormElements(&$html) { // STATIC HTML METHOD
print_r("<P>GET: "); print_r(array_keys($_GET)); print_r("<P>POST: "); print_r(array_keys($_POST));
print_r("<P>SESSION: "); print_r(array_keys($_SESSION)); print_r("<P>");
if ((!is_array($_POST) || @sizeof(array_values($_POST)) == 0) &&
$_SESSION['hidden']) {
$html .= $_SESSION['hidden'];
} else {
/*--------------------------------------------------------------------------------------------------------------------
Set $collection to either $_POST (if form post variables exist in $_POST) or default to $_GET
to parse through either/or and produce HTML hidden elements in either case
---------------------------------------------------------------------------------------------------------------------*/
$collection = ($_POST && is_array($_POST) && @sizeof(array_values($_POST)) > 0) ? $_POST : $_GET;
foreach ($collection as $key => $val) {
if (!is_array($val)) {
$hiddenHTMLRetainer .= "<input type=\"hidden\" name=\"$key\" value=\"$val\">\n";
$html .= "<input type=\"hidden\" name=\"$key\" value=\"$val\">\n"; // ADD FROM QS TO PASS BACK
} else {
foreach ($val as $innerKey => $indivVal) {
if ($indivVal) {
$hiddenHTMLRetainer .= "<input type=\"hidden\" name=\"${key}[";
$html .= "<input type=\"hidden\" name=\"${key}[";
if (!is_numeric($innerKey)) $html .= $innerKey; // NUMERICAL KEYS DO NOT NEED TO BE PLACED INTO HTML ARRAY-FORMATTABLE FORM ELEMENTS
if (!is_numeric($innerKey)) $hiddenHTMLRetainer .= $innerKey;
$html .= "]\" value=\"$indivVal\">\n"; // PUT IN INDIVIDUAL ARRAY ELEMENTS
$hiddenHTMLRetainer .= "]\" value=\"$indivVal\">\n";
}
}
}
}
$_SESSION['hidden'] = $hiddenHTMLRetainer;
global $PHPSESSID;
print_r("PHPSESSID = "); print_r($PHPSESSID); print_r("<P>");
print_r('SESSION after setting it is: '); print_r(array_keys($_SESSION));
}
return $html;
}
}
Now, in the search results page I click a link to sort my results. The link takes me back to, you guessed it, index.php (in fact, every single portion of my application literally has only one address: "index.php" and nowhere else). The moment I do that, this is what I see:
PHPSESSID = a964d0d6683757cafbe5576737ea5bf9
SESSION the moment you first enter this script of /mu-spin/image_catalog/index.php is: Array ( [0] => search [1] => sql )
GET: Array ( [0] => section [1] => search [2] => isSort [3] => sortBy )
POST: Array ( )
SESSION: Array ( [0] => search [1] => sql )
PHPSESSID = a964d0d6683757cafbe5576737ea5bf9
SESSION after setting it is: Array ( [0] => search [1] => sql [2] => hidden )
This is totally wrong!!! The $SESSION['hidden'] variable is gone!!! It is, in fact, erroneously RESET once again (with the wrong values), whereas it was supposed to have been retained within $SESSION superglobal array, yet it is not.
I hope this makes it a bit more clear as to what is literally going on.
Synopsis:
1) I go to index.php
2) I see $SESSION
3) I submit form elements
4) I see $SESSION
5) I add $SESSION['sql'] in generateSearchSQL() method
6) I add $SESSION['hidden'] in SearchView::retainFormElements() method
7) I see $SESSION with both elements
8) I click a link to go back to index.php
9) I see $SESSION.. with just 'sql' and NOT 'hidden'
10) I tear my hair out, what little I have left!
Phil