• No results found

Forms and URLs

In document ZEND PHP 5 Certification (Page 117-123)

Most often, your script will interact with their clients using one of two HTTP meth- ods: GET and POST. From a technical perspective, the main difference between these two methods is in the fact that the latter allows the client to send along a data pay- load, while the former only allows you to send data as part of the query string.

This, of course, doesn’t mean that you can’t submit a form using GET—only that you will be somewhat limited in the size and type of data that you can send. For example, you can only upload files using POST, and almost all browsers implement limitations on the length of the query string that confine the amount of data you can send out with a GET operation.

i

Contrary to popular belief, POST isnot an inherently more secure to submit forms

than GET. We explain this concept in greater detail in theSecurity chapter.

From an HTML perspective, the difference between GET and POST is limited to the

actionattribute of the <form> element:

<!--Form submitted with GET-->

<form action="index.php" method="GET">

List: <input type="text" name="list" /><br /> Order by:

<select name="orderby">

<option value="name">Name</option> <option value="city">City</option> <option value="zip">ZIP Code</option> </select><br />

<select name="direction">

<option value="asc">Ascending</option> <option value="desc">Descending</option> </select>

</form>

<!--Form submitted with POST-->

<form action="index.php" method="POST">

<input type="hidden" name="login" value="1" /> <input type="text" name="user" />

<input type="password" name="pass’ /> </form>

GET and URLs

When a form is submitted using the GET method, its values are encoded directly in the query string portion of the URL. For example, if you submit the form above by enteringuserin theListbox and choosing to sort byNameinAscendingorder, the browser will call up ourindex.phpscript with the following URL:

http://example.org/index.php?list=user&orderby=name&direction=asc

As you can see, the data has been encoded and appended to the and of the URL for our script. In order to access the data, we must now use the$_GETsuperglobal array. Each argument is accessible through an array key of the same name:

echo $_GET[’list’];

You can create arrays by using array notation...

http://example.org/index.php?list=user&order[by]=column&order[dir]=asc

..and then access them using the following syntax:

echo $_GET[’order’][’by’];

100Web Programming

Note that, clearly, there is nothing that stops you from creating URLs that already contain query data—there is no special trick to it, other than the data must be en- coded using a particular mechanism that, in PHP, is provided by theurlencode()

function:

$data = "Max & Ruby";

echo "http://www.phparch.com/index.php?name=" . urlencode ($data);

The PHP interpreter will automatically decode all incoming data for us, so there is no need to executeurldecode()on anything extracted from$_GET.

Using POST

When sending the form we introduced above with themethodattribute set topost, the data is accessible using the$_POSTsuperglobal array. Just like$_GET,$_POSTcontains one array element named after each input name.

if ($_POST[’login’]) {

if ($_POST[’user’] == "admin" && $_POST[’pass’] == "secretpassword") {

// Handle login

} }

In this example, we first check that the submit button was clicked, then we validate that the user input is correct.

Also, similarly to GET input, we can again use array notation:

<form method="post"> <p>

Please choose all languages you currently know or would like to learn in the next 12 months.

</p> <p>

<label>

<input type="checkbox" name="languages[]" value="PHP" /> PHP

</label> <label>

<input type="checkbox" name="languages[]" value="Perl" /> Perl

</label> <label>

<input type="checkbox" name="languages[]" value="Ruby" /> Ruby

</label> <br />

<input type="submit" value="Send" name="poll" /> </p>

</form>

The form above has three checkboxes, all namedlanguages[]; these will all be added individually to an array calledlanguages in the$_POSTsuperglobal array—just like when you use an empty key (e.g. $array[] = “foo”) to append a new element to an existing array in PHP. Once inside your script, you will be able to access these values as follows:

foreach ($_POST[’languages’] as $language) {

switch ($language) {

case ’PHP’ :

echo "PHP? Awesome! <br />";

break;

case ’Perl’ :

echo "Perl? Ew. Just Ew. <br />";

break;

case ’Ruby’ :

echo "Ruby? Can you say... ’bandwagon?’ <br />";

break;

default:

echo "Unknown language!"; }

}

When You Don’t Know How Data Is Sent

If you need to write a script that is supposed to work just as well withboth GET and POST requests, you can use the $_REQUEST superglobal array; the latter is filled in using data from different sources in an order specified by a setting in yourphp.ini

102Web Programming

file (usually,EGPCS, meaningEnvironment, Get, Post, Cookie and Built-in variableS. Note that$_REQUESTonly contains cookie, GET and POST information).

The problem with using this approach is that, technically, youdon’t know where the data comes from. This is a potentially major security issue that you should be fully aware of. This problem is discussed in more detail in theSecurity chapter.

Managing File Uploads

File uploads are an important feature for many Web applications; improperly han- dled, they are also extremely dangerous—imagine how much damage allowing an arbitrary file to be uploaded to a sensitive location on your server’s hard drive could be!

A file can be uploaded through a “multi-part” HTTP POST transaction. From the perspective of building your file upload form, this simply means that you need to declare it in a slightly different way:

<form enctype="multipart/form-data" action="index.php" method="post"> <input type="hidden" name="MAX_FILE_SIZE" value="50000" />

<input name="filedata" type="file" /> <input type="submit" value="Send file" /> </form>

As you can see, theMAX_FILE_SIZEvalue is used to define the maximum file size al- lowed (in this case, 50,000 bytes); note, however, that this restriction is almost en- tirely meaningless, since it sits on the client side—since any moderately crafty at- tacker will be able to set this parameter to an arbitrary value, you can’t count on it preventing any attempt to overwhelm your system by sending files that are so large as to deplete its resources.

i

You can limit the amount of data uploaded by a POST operation by modifying a number of configuration directives, such as post_max_size, max_input_time and

upload_max_filesize.

Once a file is uploaded to the server, PHP stores it in a temporary location and makes it available to the script that was called by the POST transaction (index.php

in the example above). It is up to the script to move the file to a safe location if it so chooses—the temporary copy is automatically destroyed when the script ends. Inside your script, uploaded files will appear in the$_FILESsuperglobal array. Each element of this array will have a key corresponding to the name of the HTML element that uploaded a file (filedatain our case). The element will, itself, be an array with the following elements:

name The original name of the file

type The MIME type of the file provided by the browser

size The size (in bytes) of the file

tmp_name The name of the file’s temporary location

error The error code associated with this file. A value of

UPLOAD_ERR_OKindicates a successful transfer, while any other error indicates that something went wrong (for example, the file was bigger than the maximum allowed size).

The real problem with file uploads is that most—but not all—of the information that ends up in$_FILEScan be spoofed by submitting malicious information as part of the HTTP transaction. PHP providessome facilities that allow you to determine whether a file upload is legit. One of them is checking that theerrorelement of your file upload information array is set toUPLOAD_ERR_OK. You should also check thatsizeis not zero and thattmp_nameis not set tonone.

Finally, you can use is_uploaded_file() to determine that a would-be hacker hasn’t somehow managed to trick PHP into building a temporary file name that, in reality, points to a different location, andmove_uploaded_file()to move an uploaded file to a different location (a call to the latter function also checks whether the source file is a valid upload file, so there is no need to callis_uploaded_file()first):

One of the most common mistakes that developers make when dealing with up- loaded files is using thenameelement of the file data array as the destination when moving it from its temporary location. Because this piece of information is passed by the client, doing so opens up a potentially catastrophic security problem in your code. You should, instead, either generate your own file names, or make sure that you filter the input data properly before using it (this is discussed in greater detail in theSecurity chapter).

104Web Programming

GET or POST?

PHP makes it very easy to handle data sent using either POST or GET. However, this doesn’t mean that you should choose one or the other at random.

From a design perspective, aPOSTtransaction indicates that you intend to modify data (i.e.: you aresending information over to the server). AGET transaction, on the other hand, indicates that you intend toretrieve data instead. These guidelines are routinely ignored by most Web developers—much to the detriment of proper programming techniques. Even from a practical perspective, however, youwill have to use POST in some circumstances; for example:

• You need your data to be transparently encoded using an arbitrary character set

• You need to send a multi-part form—for example, one that contains a file • You are sending large amounts of data

In document ZEND PHP 5 Certification (Page 117-123)