A morning, I woke up, and all the websites using a download system didn't work anymore. Yeah this is what I've seen. I guess I don't need to tell you that it was such a pain and that all the downloading systems on the different websites we have were not working anymore.
Such a big stress thinking that everything is broken at first, then after some time, realized that the problem is about the Content-Disposition header field which is dropped.
I wouldn't say that I would like to thank the admin that do no tell people about the modification... Anyway, I guess this is every time like that?
The Content-Disposition HTTP header field is used to explain to the browser how the data are presented. I basically use it in order to force a download system using such php script:
<?php
// download.php
// some checks on the $fname, variable to be sure
// it exists and is in the allowed directories...
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, pre-check=0");
header("Content-Type: application/octet-stream");
header("Content-Length: " . filesize($fname));
header("Content-Disposition: attachment; filename=".basename($fname));
header("Content-Description: File Transfer");
@readfile($fname);
exit;
?>
Now, if you cannot submit the Content-Disposition field, then the browser will download the file called "download.php". A quite simple solution, is to fool the browser by making the name of the reachable URI the same as the file it should download, using Mod_Rewrite.
RewriteEngine On RewriteBase /mydir RewriteRule ^download/([^/]+)$ /mydir/download.php?file_redir=$1
And just a simple modification in the original script in order to detect the "file" GET variable. But since we don't want to modify all the (generated or not) HTML files, we need to make the redirection automatically.
<?php
// download.php
// some checks on the $fname, variable to be sure
// it exists and is in the allowed directories...
if (isset($_GET['file_redir'])) {
$fname = $_GET['file_redir'];
// checks for good files (careful of directory traversal etc.)
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, pre-check=0");
header("Content-Type: application/octet-stream");
header("Content-Length: " . filesize($fname));
header("Content-Description: File Transfer");
@readfile($fname);
exit;
}
else {
header("Location: /mydir/download/$fname");
exit;
}
?>
Then you don't have to change all your pages. This is of course a (not so?) temporary solution since the server will do extra work in order to go to the same state, the download of the file, but well, it does the job to fool the browser...


Last comments