I am passing a filename to a download page.
ie somefile.xls
The download page adds back in the full directory path onto the filename.
ie c:\temp\somefile.xls
The problem is that now setting the 'Content-Disposition' of the header doesn't work. The filename it wants to download is the full directory-filename path. ie c_temp_somefile
Can the Content-Disposition handle a full path?
If it can how do I get my script to properly download the file?
Code is:
$myad = $_GET['myad'];
$glob_string = realpath('/foldera/folderb/folderc'). DIRECTORY_SEPARATOR .$myad;
header('Content-Type: application/excel');
$headerstring = 'Content-Disposition: attachment; filename='.$glob_string;
header($headerstring);
readfile($myad);
UPDATED code (from answers):
$myad = $_GET['myad'];
$glob_string = realpath('/mit/mit_tm/mrl_bol'). DIRECTORY_SEPARATOR .$myad;
header('Content-Type: application/excel');
$headerstring = 'Content-Disposition: attachment; filename='.$myad;
header($headerstring);
readfile($glob_string);
In a regular HTTP response, the Content-Disposition response header is a header indicating if the content is expected to be displayed inline in the browser, that is, as a Web page or as part of a Web page, or as an attachment, that is downloaded and saved locally.
Content-Disposition is an optional header and allows the sender to indicate a default archival disposition; a filename. The optional "filename" parameter provides for this. This header field definition is based almost verbatim on Experimental RFC 1806 by R. Troost and S.
1. Content Disposition Type : inline: This indicates that data should be displayed automatically on prompt in browser. attachment: This indicates that user should receive a prompt (usually a Save As dialog box) to save the file locally on the disk to access it.
The MIME Content-disposition header provides presentation information for the body-part. It is often added to attachments specifying whether the attachment body part should be displayed (inline) or presented as a file name to be copied (attachment).
Don't pass the full path via the header string, but use the base name ($myad
) instead.
You should really use a better validation for $_GET['myad']
, since your script will pass arbitrary paths to the user (readfile()
gets the unfiltered user input). This is a security hole!
Calculate the real path using realpath
, make sure that the file is within a allowed folder, then use basename()
on the full path to get the plain file name. Pass this substring via the Content-Disposition
header, but use the real path for readfile()
.
UPDATE: Your updated code still contains a security hole. If $_GET['myad']
contained ../../../some/full/path
, your script would happily send any requested readable file to the client.
You should use something along the lines of the following snippet:
$myad = $_GET['myad'];
$rootDir = realpath('/mit/mit_tm/mrl_bol');
$fullPath = realpath($rootDir . '/' . $myad);
// Note that, on UNIX systems, realpath() will return false if a path
// does not exist, but an absolute non-existing path on Windows.
if ($fullPath && is_readable($fullPath) && dirname($fullPath) === $rootDir) {
// OK, the requested file exists and is in the allowed root directory.
header('Content-Type: application/excel');
// basename() returns just the file name.
header('Content-Disposition: attachment; filename=' . basename($fullPath));
readfile($fullPath);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With