php download file

Hi i'm trying to download a file from the file "upload". I'm using thin cobe but the result is "I'm sorry, the file doesn't seem to exist"

here is my call

<a href="download.php?filename=<?php $row4['Arxeio'] ?>">Click here
to Download the File</a>

and download.php

<?php  session_start();

$filename = $_GET['filename'];

$download_path = './upload/';

if(eregi("\.\.", $filename)) die("I'm sorry, you may not download that file.");

$file = str_replace("..", "", $filename);
// Make sure we can't download .ht control files. if(eregi("\.ht.+", $filename)) die("I'm sorry, you may not download that file.");

// Combine the download path and the filename to create the full path to the file. $file = '$download_path$filename';

// Test to ensure that the file exists. 
if(!file_exists($file)) die("I'm sorry, the file doesn't seem to exist.");
// Extract the type of file which will be sent to the browser as a header
$type = filetype($file); // Get a date and timestamp $today = date("F j, Y, g:i a"); $time = time(); // Send file headers header("Content-type: $type"); header("Content-Disposition: attachment;filename=$filename");
header("Content-Transfer-Encoding: binary"); 
header('Pragma: no-cache'); 
header('Expires: 0'); // Send the file contents.
set_time_limit(0); 
readfile($file);
?>

Upvotes: 1

Views: 10649

Answers (1)

Michael Berkowski
Michael Berkowski

Reputation: 270727

In your HTML, you need to echo the filename for it to be written to output:

<a href='download.php?filename=<?php echo $row4['Arxeio']; ?>'>Click here to Download the File</a>

When receiving the filename in PHP, you must validate it against directory traversal attacks. Verify that it contains no / or ... You have a rudimentary test with eregi() (which is deprecated, by the way), but it can be done simply with strpos().

if (strpos($filename, "..") >= 0 || strpos($filename, "/") >= 0) {
  // Error! don't permit file download
}

Review PHP's documentation on NULL byte attack protection as well.

Better though, would be to compare the $filename against a whitelist of valid filenames for download:

if (in_array($filename, array('file1.jpg', 'file2.txt', 'file3.mov',...)) {
  // Ok, send the file.
}
else {
  // Invalid file
}

Upvotes: 3

Related Questions