Example script to receive published files
<?php
/* this is an example of how a published file can be received from
Ensembling automatically. This assumes we do all the provided
security checks, but a form that already exists to do a file upload
can work without these. */
$file_field = 'file'; /* the name of the field in the $_FILES array
containing the file; the Ensembling user can
also set this, and obviously both sides have to
agree on what it is called, but this is the default. */
$file_destination = '/home/me/importedfiles'; /* where on this server to put the file received
- don't forget the web server will need write
access to this directory */
$security_field = 'security'; /* the name of the field in $_POST where
Ensembling provides security check
information; the Ensembling user can
change this name, but both ends have to
agree on it; this is the default. */
$security_secret = '123456'; /* change this to a private value and enter
it as Ensembling's security secret; this is
our shared secret */
$expected_source_url = 'www.ensembling.com'; /* where the upload is coming form */
/* -------------------------------------------------- */
/* did the post come from Ensembling: check the IP address. Remove
this section if the upload mechanism is for use from other clients as
well */
if (empty($_SERVER['REMOTE_ADDR']) ||
$_SERVER['REMOTE_ADDR'] != gethostbyname($expected_source_url))
{
do_403('dont know you');
}
/* -------------------------------------------------- */
/* if this is not a post, send a 202 to acknowledge the request
(Ensembling tries a test for this). Not essential: a simple exit
will do if there is no $_POST */
if (empty($_POST)) { do_202('ping OK'); }
/* -------------------------------------------------- */
/* check the security. This is specific to Ensembling, so remove this
section for general utiltiy, or if you are not bothered about this
cross check. It sends a string in the nominated POST variable which
is in two parts separated by a space. The first part is a 9 digit
random number (different every time) and the second is an sha1
encryption of the shared secret number concatenated with the random
number. So by recreating and comparing the encrypted part this end
from the shared secret and the given number we can check that the
sender knows our shared secret */
if (empty($_POST[$security_field])) { do_403('missing security'); }
if (strpos($_POST[$security_field], ' ') === FALSE) { do_403('security bad format'); }
list($plaintext, $encryptedtext) = explode(' ', $_POST[$security_field]);
if (sha1($security_secret . $plaintext) != $encryptedtext) { do_403('security check failed'); }
/* -------------------------------------------------- */
/* OK, we're now in a position to receive the file. (Consider what to
do with any other post params that you may want processed, not
illustrated here, bearing in mind we don't know the file suceeded
transfering yet; for example, you might have a field which tells this
script to email someone to say the file has arrived, or a field to vary
which directory the file is uploaded to). */
if (empty($_FILES[$file_field])) { do_400('no file'); }
switch ($_FILES[$file_field]['error']) {
case 0:
case UPLOAD_ERR_NO_FILE:
break;
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
do_413('too big');
case UPLOAD_ERR_PARTIAL:
do_500('partial transfer');
default:
do_400('unknown error');
}
$file_name = $_FILES[$file_field]['name'];
/* at the very least ban php etc, invoked by the web server. Be very
careful if other file suffixes are handled unusually by the web
server, e.g. if HTML files are executed by the PHP server, as any
PHP code in there could then do anything. Much better to put the
files outside the web server and fetch them yourself with PHP */
if (substr($file_name, -3) == '.php' ||
substr($file_name, -2) == '.pl' ||
substr($file_name, -2) == '.py')
{
do_403('file type not allowed');
}
/* replace any non-permitted characters, so we can be sure we can save the file */
$path_name = $file_destination . '/' . rawurlencode($file_name);
if (! move_uploaded_file($_FILES[$file_field]['tmp_name'], $path_name)) {
do_500('cannot save file');
}
/* -------------------------------------------------- */
/* otherwise, give some clue that it was all ok */
echo <<<EOD
<html>
<head><title>upload OK</title></head>
<body><p>file uploaded correctly</p></body>
</html>
EOD;
/* -------------------------------------------------- */
function do_http_error($code, $s) { header("HTTP/1.0 {$code}"); echo $s; exit(); }
function do_202($s) { do_http_error('202 Accepted', $s); }
function do_400($s) { do_http_error('400 Bad Request', $s); }
function do_403($s) { do_http_error('403 Forbidden', $s); }
function do_404($s) { do_http_error('404 Not Found', $s); }
function do_413($s) { do_http_error('413 Request Entity Too Large', $s); }
function do_500($s) { do_http_error('500 Internal Server Error', $s); }
?>