Creating a SECURE file manager with PHP
(Page 2 out of 3)Uploading files
Our original code for uploading files is still fine, except instead of simply copying the uploaded file to the upload directory, we must now open the file, copy the data, and then write a new protected file in the upload directory, like so:
$data = implode('', file($_FILES['file']['tmp_name']));
// Create new 'protected' file
$file = '' . "\n";
$file .= base64_encode($data);
// Write new file
$newfile = $path . $_FILES['file']['name'] . '.php';
$f = fopen($newfile, 'w');
fwrite($f, $file);
fclose($f);
// Remove temporary file
unlink($_FILES['file']['tmp_name']);
The above code first gets the file data, and then creates the new 'protected file', by adding the protection line, and the data (sent through the base64_encode() function so nothing harmful can be inserted). After that it writes the new file to the upload directory, and removes the temporary file.
That's all we have to change in the upload script, and if you want to have a look at the full script, click here to download the complete source.
Downloading files
We must also customize the streaming script somewhat, to account for the protection line and the base64 encoding. The biggest change is that the script now uses the following code:
$data = file($filepath);
array_shift($data);
$data = implode('', $data);
$data = base64_decode($data);
to get the file data, instead of simply using the readfile() function. The above code first gets the file data using the file() function, which means every line of the file is a separate element in an array. It then removes the protection line, as this was not part of the original file data. After it runs the data through the base64_decode() function to get back the original data.
There are a few more subtle changes, such as using the strlen() function to send the Content-Size header, instead of the filesize() function, but these are hardly worth discussing. Have a look at the full source to view all the changes.
Editing & Deleting files
The edit script also has to change slightly, because the protection line has to be removed from the file, just like with the streaming script, and the exact same code is used, i.e.:
$data = file($filepath);
array_shift($data);
$data = implode('', $data);
$data = base64_decode($data);
Another change in the edit script is in the way it saves the file. Just like with the upload script, it now writes a protected file, with the protection line, using the following code:
$file = '' . "\n";
$file .= base64_encode($_POST['newfile']);
// Write new file
$f = fopen($filepath, 'w');
fwrite($f, $file);
fclose($f);
Have a look at the source code for the complete edit script.
The delete script stays almost exactly the same, except for one minor change (each file now has a .php extension, which must be accounted for). See the source code for the change.
February 22nd, 2006 at 8:56 pm
Sexy, just getting started with the whole web development thing, very excitng. i enjoyed this tutorial.
February 22nd, 2006 at 11:01 pm
Just wondering if i might get a response on this question. I get a security error when i try to do anyhting with the files, be it edit, or delete, or download. ID this due to folder restrictions, i have the permissions at 777. or should i try locating the uploads folder above my web directory as you stated in this tutorial?
April 4th, 2006 at 8:24 pm
What if instead of downloading the file, I want to use the file as an image source? For example: img src=’uploaded_file.php’ ?
August 1st, 2006 at 10:07 am
thanks very much i got a way for security purpose in files .
but can you tell me how we can upload mpeg files
August 11th, 2006 at 9:16 pm
For PHP 4.3 and higher, you can use file_get_contents() to get the file contents as a string instead of having to use implode() with file().