[main] [misc] [graphics] [page design] [site design] [xhtml] [css] [xml] [xsl] [schema] [javascript] [php] [mysql]

HVCC Home
Blackboard HVCC
Blackboard Manual
Faculty Association

php main
1. what is php
2. http basics
3. php basics
4. php expressions
5. php client side
a. writing php content
b. php global arrays
* c. php form data
d. writing the url
6. php flow control
7. php manual


print version

Note that all external links will open up in a separate window.

This is a stripped down version of these pages for older browsers. These pages are really meant to be viewed in a standards compliant browser.

Directions for surfing with audio.

Form Data Processing

These tutorials are about PHP and its use for server-side Web programming.

PHP Form Data

When you are using PHP to process information provided by the user, you are normally doing form processing. Thus, a discussion of how to retrieve data from the user is really about how to process form data submitted by the client to the server. To do this we make use one or more of the following four global arrays:

  • $_GET[] ($HTTP_GET_VARS[])
  • $_POST[] ($HTTP_POST_VARS[])
  • $_FILES[] ($HTTP_POST_FILES[])
  • $_REQUEST[]

Since file processing is an advanced topic, using the $_FILES[] array and managing files post by users wil be its own topic later. There are various reasons to be cautious about using the $_REQUEST[] array, like what happens when we have a GET field and and POST field with the same name. So for now we will stick with talking about using $_GET[] and $_POST[] to talk about how to process user data.

We will stick with using the short forms for the array names.

The Basics

The basic concept is really simple. Data returned from the client using the POST method are stored in the $_POST[] array by PHP. Data returned from the client using the GET method, or as a query string in the URL, are stored in the $_GET[]. It is possible to have both if, for instance, you have a form using a POST method that is posting to a URL that includes a query string.

The names of the elements in the arrays directly corresponds to the field names in the form and/or query string. For instance:

<form method="POST" action="myscript.php?flag=yes">
  <p>
  <input type="text" name="field1" /> Sample field
  </p>
[...]

The above coding snippet would generate a $_GET[] elements called $_GET["flag"] and have the value of "yes". It would also create a $_POST[] element called $_POST["field1"] and having the value entered into the form field by the user.

To retrieve a value, you just check the array element in $_GET[] or $_POST[] with the same name as the form field. It is that simple. With a little creative coding, you don't even need to know what the form fields are called in advance, you can just walk the arrays. Although you do need to know what the fields are in order to know what to do with their content.

Tips and Tricks

There are numerous little bits of information that go with the task of processing form data. You can improve your coding by knowing what they are. The following is a list of tips and tricks of for processing form data. They are not presented in any particular order.

General Tips

Forms do not return fields that don't have values, so blank fields with no default values will not be returned to the server. Thus PHP will have to account for the fact that not every form field may be accounted for in the reply from the client.

For checkboxes, if a value has not been provided in the HTML code, will return a value of "on". Usable, but you should always provide a value for these fields to return.

For compatibility with all systems, it is recommended that you write "GET" and "POST" in upper-case, thus method="POST" and not method="post".

If, for some reason, you don't know the requesting method the client is using, it is stored by name in $_SERVER["REQUEST_METHOD"].

Data validation in PHP is more robust than data validation in JavaScript. Data validation on the server is in general more robust than client-side data validation. You should always revalidate form data on the server. CLient-side validation is just to avoid unecessary calls to the server.

GET requests are cached when received by the client. A call to the same resource with the same query string may return the cached version instead of rechecking the server. If using a GET method with extremely time sensitive data,you should make sure that caching is turned off for the page.

Here are the PHP commands to write out HTTP headers to tell the browser not to cache:

// Set past expiration date
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");

// Define mod date to indicate page is modified
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");

// HTTP 1.1 cache commands
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);

// HTTP 1.0 cache commands
header("Pragma: no-cache");

You can also use the following HTML meta tag to set a past expiration date.

<meta http-equiv="expires" content="Sun, 01 Dec 2001 12:00:00 EST" />

Resource requests using POST are always refreshed against the server. They are not cached. You should always use the POST method if the result data may change when the form data does not change.

Form Field Names

If the name of the form filed contains characters that are illegal characters for the array index key names, the characters will be replaced with underscores.You should code your forms to not have illegal characters in the field names.

If a form field can have multiple values, such as a selection field with multiple turned on, or a set of checkboexes that all have the same name because they represent possible values for the same variable, you are going to have a situation of multiple values being sent back to the server. Under normal conditions, only the last one processed will be saved in the array. There is an easy work around for this.

To submit multiple values from a single field name to PHP end the field name with square brackets. To avoid URL encoding problems, using the POST method is preferred for this. PHP will recognize that the values are a set of value and create an array to store them. The value of the $_POST[] array element by that name will be an array containing those values. Yes, that is a nested array.

<form method="POST" action="myscript.php?flag=yes">
  <p>
  <input type="checkbox" name="field1[]" value="1" />
    Sample 1
  <br />
  <input type="checkbox" name="field1[]" value="2" />
    Sample 2
  <br />
  <input type="checkbox" name="field1[]" value="3" />
    Sample 3
  </p>
[...]

The above form fields will generate an array that will be stored in $_POST["field1"] with a value stored for each one selected. The first value could be accessed with $_POST["field1"][0] or by assigning the element value to another array and accessing that.

$field1Arr = $_POST["field1"];
$firstVal = $field1Var[0];

Practicing Safe Data Processing

When working with user supplied data, you need to be aware of the fact that you are opening yourself up to attacks from malicious users, and, to be most honest, mistakes by users who are not the brightest bulb in the room. You need to be able to code for this.

Coding for unsers who don't know what they are doing is a simple matter of thinking through the process carefully, providing clear directions, and testing everything to make sure the directions are followed. This is a guiding principle of good software design. Unfortunately, this is not the place for a detailed looked at best practices in GUI interface design. It is really a field of study in and of itself. So, for now, let us say, make sure forms are clear, comprehensible and easy to use, and test everything coming back from the client for every possible mistake you can think of. Then ask other people to think of more possible mistakes to code for,

Instead we are going to look at how to reduce attacks on your system, both intentional and accidental, instigated through HTML forms processing code. The biggest hazard involves posting files to the server, which we discuss elsewhere. For now we will focus on two issues:

  • Users sending malicious code through HTML forms fields
  • Users spoofing HTML form fields.

Bad Data

It is possible for a user to send bad data through form fields. Properly conceived, this can be used to get confidential information back from the server or hack into the system.

The first step to avoiding this is to make sure that register_globals is not enabled. This is discussed below. The next step is to make sure there aren't any commands in the data being sent that could be accidentally excecuted by PHP.

We can get rid of most commands in content being sent to the server simply by getting rid of the angle brackets, since a PHP command would need to begin with <?php for it to exectute. We can do this with the htmlSpecialChars() function. It takes a string as an argument and returns the string with all HTML special characters converted to their special character equivalents. Thus < becomes &lt; and so on. This will take care of most potential attacks.

If you are working with shell commands, there is a escapeShellArg() function which does a simliar thing for Unix commands. This prevents users from exeucting commands that pipe or inculding multiple commands in a single field.

It is, of course, preferable to not let users execute any commands on your system, but this is not always possible.

Don't be afraid to test user data for every eventuality and to restrict it to clearly defined sets of values. Both of these make your security job easier.

For instance, the search strings on these pages identify where the page is and what it is called, but rather than directly addressing the page, they are used to look the page up in an array. The array tells where to get the page. This keeps someone from being able to spoof the search string and request documents I don't want them to have.

Form Field Spoofing

Users, with some clever coding, can send data to your server which spoof a form submission from the page but contain field names that are not part of the form. This may seem pointless, but can be used to override system variables and thus allow them to hack into the server. For instance, by getting the server to echo out the password file.

The simplest solution to this is to make sure that register_globals is turned off in the PHP initialization file. For newer version of PHP this is the default. Registering globals is the process of taking all the values in the global arrays and assigning them to variables whose names match the index keys of those elements in their respective arrays. Enabling register_globals automates the process so that PHP does it automatically when the script is loaded. Otherwise you have to do it manually.

When it comes right down to it, the only reason for having an automated process for registering globals is laziness. It is not worth the security risk, so don't enable register_globals.

If you do have a better reason and do need to enable register_globals, then there are some precaustions you can take. The directive variables_order allows you to specify the order in which globals are to be registered. The default value for it is EGPCS, which converts them in the following order:

  • $_ENV
  • $_GET
  • $_POST
  • $_COOKIE
  • $_SERVER

Note that server variables are last, preventing them from being overwritten by user data. However, the user could still use cookie data to spoof posted data, thus causing the server to think that the fiel they had uploaded was actually your password file or somesuch (and could you please echo back the contents to make sure it posted correctly).

Since anything not in the list will not be processed, you can enhance security by inly registering those you need, or only system variables, using the global arrays for the rest. Thuse we could change it to variables_order="ES" and maintain a reasonable level of security, though we would still need to use the long method to access user data.

Even with register_globals turned off, it still pays to screen the input for spoofed fields. The best way to do this is only allow user data to be written to variables that already exist. You can do this by explicitly initializing the variables in your code than only accepting content from the user data arrays that are associated with variables that already exist in the code. The code would look something like this:

$formField1 = '';
foreach ($_POST as $key => $value) {
  if (isset(${$key}) {
    ${$key} = $value;
    }
  }

[top]