Reputation: 2251
Is it possible to use .htaccess to route zip file requests to the level of public_html, if open_basedir is in effect?
The reason I'm asking is because I'm trying to force a download of any of the zip files which are on the same level as public_html / www, if a visitor clicks on a seemingly direct download link.
An extremely simplified code for what I'm trying to make could look something like this.
.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*)\.(zip)$ dl.php?filename=$1 [L,QSA]
index.php
//various bits of php code, and this below
<div>
<a href="1.zip">1</a>
</div>
<div>
<a href="2.zip">2</a>
</div>
<div>
<a href="3.zip">3</a>
</div>
dl.php
$file = "../../".$_GET['filename'].".zip";
header('Content-type: application/zip');
header('Content-length: ' . filesize($file));
readfile($file);
die();
Should I even be doing it like this, or is there a better way? I'm just trying to do this for one specific filetype, available on one specific page (index.php, in the example), so I'm not really looking to make an entire routing system just for this.
Upvotes: 0
Views: 55
Reputation: 20747
Assuming that your .htaccess
works properly then you would need dl.php
to do something like this in order to be secure:
$directory = '../../';
// Get the a file listing from the directory which contains the files
foreach(array_diff(scandir($directory), array('..', '.')) as $file)
{
if(
strtolower($file) === strtolower($_GET['filename'].'.zip') && // Check each filename against the requested filename in $_GET. Use strtolower() for case-insensitive filesystems
is_file($directory.$file) // Make sure that this is a file and not a folder
)
{
// Serve it up!
header('Content-type: application/zip');
header('Content-length: ' . filesize($directory.$file));
readfile($directory.$file);
die();
}
}
Upvotes: 1