PHP FormMail,
Form Encryption
 
Uploading Files

This HOW TO guide describes the steps required to configure your HTML form and FormMail to allow file uploads.

From version 2.00 of FormMail, uploaded files were attached to the email sent to you. From version 7.08 of FormMail, uploaded files can be optionally stored on the server, instead.

Your HTML Form

Firstly, the HTTP protocol requires that you specify a particular encoding for the form submission. This encoding is specified in the HTML form tag with the enctype attribute.

<form method="post" action="http://your-site.com/formmail.php" name="SampleForm" enctype="multipart/form-data" />

Next, you create form fields to specify file uploading. FormMail does not place a limit on the number of files you can upload.

<p>File to upload: <input type="file" name="first_file" /></p>
<p>File to upload: <input type="file" name="second_file" /></p>

FormMail

File uploading can represent a minor security problem for you. For example, an attacker could bypass your HTML form and use FormMail to send you many unwanted files. For this reason, the default for FormMail is to disallow file uploads.

To enable file uploads, look for the FILEUPLOADS setting in FormMail's configuration section and set it to "true", like this:

define("FILEUPLOADS",true); // set to true to allow file attachments

Your Server

Most PHP installations allow file uploads by default. You may, however, need to contact your hosting provider and ask them to enable file uploads. The setting is in the server's php.ini file and is called upload_tmp_dir.

Limiting the File Upload Size

There is usually a maximum file size allowed for uploading files in PHP. This setting is also specified in the php.ini file and is called upload_max_filesize. The default is usually 2 megabytes. If you need a larger limit, you may need to contact your hosting provider.

On some servers, you can override this yourself in your own .htaccess file:

php_value upload_max_filesize "3M"

this will set the upload limit to 3 megabytes for a FormMail script located in the same directory as the .htaccess file.

If you want a smaller maximum size for file uploads, PHP supports a hidden field called MAX_FILE_SIZE:

<input type="hidden" name="MAX_FILE_SIZE" value="25000" />

In this example, PHP will limit the file uploads to 25,000 bytes. Note, however, this is easily bypassed by an attacker, so you shouldn't rely on it to protect you or your server.

Therefore, FormMail provides you with a secure way of limiting the size of uploaded files. In the configuration section look for MAX_FILE_UPLOAD_SIZE:

define("MAX_FILE_UPLOAD_SIZE",30); // default of 0 means that other software

FormMail interprets this setting in kilobytes. So, 30 means 30,720 bytes. If you set this value to zero, then FormMail does not enforce a limit on the uploaded file size (so any limit imposed will be by other systems as described above).

Using Conditions and Required

FormMail allows your HTML forms to control your user's file uploads using required and conditions. Review the HOW TO guide for these features for full details. Briefly, when you use the name of a file field in required, FormMail checks whether a file has been uploaded.

When you use the name of a file field in a conditions string comparison, FormMail substitutes the name of the file the user uploaded (the name of the file on the user's computer).

When used in a conditions numeric comparison, FormMail substitutes the size of the file in bytes.

Here's an example of checking that a file has been uploaded using required:

<input type="hidden" name="required" value="first_file:Please upload a file." />

This is the same example using conditions:

<input type="hidden" name="conditions1" value=":@
   @TEST@first_file@Please upload a file.@" />

Here's an example of checking the file name provided the file has been uploaded (this example checks that the file ends in .pdf):

<input type="hidden" name="conditions1" value=":@
   @IF@first_file@first_file~/^.*\.pdf$/i@@You can only upload PDFs@" />

Here's an example of checking the file size provided a file has been uploaded:

<input type="hidden" name="conditions1" value=":@
   @IF@first_file@first_file#<10240@@Maximum file upload size is 10 kilobytes.@" />

This example checks that the file has been uploaded and checks the name of the file and its size:

<input type="hidden" name="conditions1" value=":@
   @TEST@first_file@Please upload a file.@:
   @TEST@first_file~/^.*\.(pdf|jpg|jpeg|gif|png)$/i@You can only upload PDF or graphics files@:
   @TEST@first_file#<10240@Maximum file upload size is 10 kilobytes.@" />

Storing Uploaded Files on the Server

By default, FormMail attaches uploaded files to the email it sends you with the results of the form submission. You can, however, direct FormMail to store uploaded files on your server instead of emailing them to you.

To do this you need to create a directory or folder on your server. We call this the file repository. The file repository can be within or outside your web server document root. If you want to ensure the files are not downloadable from the web, we recommend you put the file repository outside (above) the document root.

The file repository must be writable by the web server software. In most cases this means you need to "chmod" the directory you create as mode 777 or rwxrwxrwx.

Once you've created the directory for the file repository, you need to know its full pathname. You then set this value in FormMail's configuration setting called $FILE_REPOSITORY:

$FILE_REPOSITORY = "/home/your-site/filerepos";

The actual directory or folder path will depend on your server.

Setting File Permission Modes

When an uploaded file is stored on your server you may want to control the permission modes. You can control the file permission modes with the FILE_MODE configuration setting in FormMail. Review the documentation above this setting in formmail.php for full details.

Renaming Files

You can direct FormMail to rename the files that are uploaded. For example, your users will typically upload files with a variety of different names. In particular, you may want to indicate which field the file was uploaded in if your form allows multiple file uploads.

You rename files using the file_names hidden field. The syntax and features of this field are similar to deriving fields from other fields.

This example prefixes the file name with a field identifying string:

<input type="hidden" name="file_names" value="
   first_file=%'File1-'%.first_file,
   second_file=%'File2-'%.second_file" />

This example prefixes the file name with the date:

<input type="hidden" name="file_names" value="first_file=%date%.first_file" />

This example identifies the two files uploaded by the users who uploaded them:

<input type="hidden" name="file_names" value="first_file=realname.%'-file1'%, second_file=realname.%'-file2'%" />

The file_names feature does two things:

  1. Sets the name of the uploaded file for storage or email attachment.
  2. Creates (derives) a new field called "name_of_X", where X is the name of the file field. You can use this new field just like any other derived field. The above examples would create new fields called "name_of_first_file" and "name_of_second_file", whose values would be the new names for the files. Note however, the creation of the "name_of_" fields occurs after normal field derivations, so you cannot use these new fields in a derive_fields specification.

File renaming works with files stored on the server and also files attached to email.