This is the second time in as many weeks that we have been bitten by the
fact that $_POST != $HTTP_POST_VARS;  Attached is a real-world example of
why it is currently bad practice to use the _POST variables.

I cannot recommend that anyone use $_POST[..] in their scripts.
$GLOBALS['HTTP_POST_VARS'][..] is a much safer, portable, and sane
solution, unless $HTTP_POST_VARS is marked as depracated, scheduled to be
phased out.

For those new to the problem, $_GET and $HTTP_GET_VARS are two totally
separate arrays which happen to hold the same data at the beginning of
script execution.  After script execution has begun, it is VERY DANGEROUS
to modify the data contained in either of these arrays, because changes
in one are not propagated to the other.

The simplest example script is:
<?php
  echo $_GET['test'];
  echo $HTTP_GET_VARS['test'];
  $_GET['test'] = 'changed.';
  echo $_GET['test'];
  echo $HTTP_GET_VARS['test'];
?>

...The second set of echo statements will print two different values.

The situation is worse when you are trying to integrate the usage of
$_GET/$_POST into scripts which already make use of $HTTP_*_VARS.

The following script is my real-world example of a difficult to trace
logic bug caused by $_POST != $HTTP_POST_VARS.

The situation is that we have a form with a radio button toggling between
two input elements as follows.

  PRICING:
  --------
  ( ) Fixed: $[______]
  ( ) Negot: $[______]

The radio field is named "option", and the two input fields are named
"asking1" and "asking2" respectively.  On the back end, we store whether
the user selected "fixed" or "negotiable", and then 'push' asking1 or
asking2 into a variable called "asking_price".  We don't care which field
they type the price into, but asking1 and asking2 must be named
differently so that the browser will not stomp asking prices over each
other when posting the information.

Our function "gpc" stands for "Get/Post/Cookie", and is very similar to
the new $_REQUEST array, except that it returns FALSE if nothing was
posted, preventing us from having to do: 
  if( isset($_REQUEST['blah']) ) 
    $result = $_REQUEST['blah'];

(because we run with E_NOTICE & E_ALL, and have register_globals turned off)
...instead, we can say:
   $result = gpc('blah');

...anyway, we've been using PHP for a while now (since well before 4.1
;^), and already have many many scripts and libraries which use the
HTTP_*_VARS method of accessing things.  It is unsafe to use $_GET and
$HTTP_GET_VARS in the same environment.

My proposed solutions again:

1) Temporary workaround: $HTTP_GET_VARS =& $_GET;
2) Throw an E_NOTICE if $HTTP_*_VARS or $_* is used as the left-hand side
of an assignment. (ie: officially discourage changing $HTTP_*_VARS)
3) Propagate any changes made to $_GET over to $HTTP_GET_VARS and
$_REQUEST.

#1 works for the most part, but changes is $_GET are not propagated into
$_REQUEST, which opens the door for more data inconsistency issues.

#2 could possibly be implemented by making $HTTP_*_VARS and $_* into
constants... forcing them to be read only.

#3 sounds like it would be annoying to implement, but would make it
easiest for end-users to use PHP, and have some nice things happen
'magically'.

--Robert
(crossposting to php.general because I'm sure other people might be
running into this problem as well).


<?PHP

## example script

/* return the user-submitted value of $varname, or false if not found */
function gpc( $varname )
{
  if( isset( $GLOBALS['HTTP_GET_VARS'][$varname] ) )
    return( $GLOBALS['HTTP_GET_VARS'][$varname];
  elseif( isset( $GLOBALS['HTTP_POST_VARS'][$varname] ) )
    return( $GLOBALS['HTTP_POST_VARS'][$varname];
  elseif( isset( $GLOBALS['HTTP_COOKIE_VARS'][$varname] ) )
    return( $GLOBALS['HTTP_COOKIE_VARS'][$varname];
  else
    return( FALSE );
}

$option = gpc('price_option');
if ( $option == 'fixed' )
{
  $_POST['asking_price'] = isset($_POST['asking1']) ? $_POST['asking1'] : '';
}
elseif ( $option == 'negotiable' )
{
  $_POST['asking_price'] = isset($_POST['asking2']) ? $_POST['asking2'] : '';
}

$price = gpc('asking_price');

echo "User chose $option, with a price of $price";
echo "(but we really only changed ${_POST['asking_price']}, so gpc()
doesn't know that!)"

?>

-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to