You are invited to Log in or Register a free Frihost Account!

Nice htaccess trick for disallowing downloading


I was playing with htaccess today and I found something neat. I have written some scripts for php-fusion (though applicable for other stuff as well, just a small modification).
It does not allow downloading files unless you are a member.

Here is my example setup:

What I want to do is to block users from going to the files/ directory and download everything. I want download.php to fetch the files for me.

When a user goes to download.php it uses GET or POST to indicate the filename in the files directory.
So lets say the user goes to download.php?file=image.bmp
This is what my download.php looks like:
if ($iMEMBER) {
   $CT='Content-Type: image/bitmap';
   if (stristr($_GET['file'],'.jpg')) {
      $CT='Content-Type: image/jpeg';
   $CD='Content-Disposition: attachment; filename="'.$filename.'"';
   } else {
   echo "Only members can acces this!<br />\n".$_GET['file'];

The .htaccess in the files directory looks like this:
<FilesMatch "\.(jpg|bmp)$">
Order deny,allow
Deny from all
Allow from

My index.php is quite easy, it looks like this:
echo "<a href='download.php?file=image.jpg'>Download image.jpg</a>";
echo "\n<br />\n";
echo "<a href='download.php?file=file.bmp'>Download file.bmp</a>";

What happens is that no one can access the jpg and bmp files in the files folder except for the server itself.
The download.php has permission and only does so when iMEMBER is valid.
If it is a member a new download starts.

This script has no checks to see whether the files exist and should include a lot of safety measures.
This can be used to create filehosts as well. This shows the basic principles of having an additional protection layers over the images. What the php script could do is refuse the file if another file has been downloaded in the last 24 hours OR allow the file because it is a registered user who has paid for the file. Smile

Hope this helps any of you. I sure learned something today Smile

EDIT: Just noticed that headers are missing. You can not see for example how big a file is so it keeps on downloading till the server says it's done. Smile
Fire Boar
In fact, the 'allow from' line is unnecessary: .htaccess doesn't prevent PHP from accessing the files, UNIX file permissions do that.
What happens if somebody tries to access download.php?file=../index.php?
If download.php is linked/shown in an <img> tag it would be better if you put the error message in a graphic so the browsers can show it, most browsers wouldn't show the error text that returned.

You can sanitize the file parameter with
$_GET['file'] = basename($_GET['file']);

You might want to try using rewrite rules in your .htaccess

RewriteEngine On
RewriteRule ^(.*).jpg$ ../download.php?file=$1.jpg [L]

or have php run a script before running the image as a php file

#php_value auto_prepend_file download.php
AddType application/x-httpd-php .jpg
AddType application/x-httpd-php .bmp

and exit() if they're not authorized, if they are have php output the file and exit or else php will treat the image as a php file and you'd have to make sure there's no <? strings in the files because php will start interpreting code
Still needs a lot of work, thanks for the replies.

@jmraker, can you explain me what the rewrite rules do?
Also is application/x-httpd-php .* a way of saying to the browser "Figure it out yourself what this file is"?

@Hogwarts, it does need a lot of security. I thought of maybe using a database instead (download.php?file=0, which returns the 0th file in the database, which is a filename. This way no weird characters can make their way in GET.

@Fire Boar, Good to know Smile
A rewrite rule tells apache that a url that matches a regular expression should be treated as if it was another url where $1 is the contents of what matched in the 1st comma part of the regex, so apache could handle a request for /files/image.jpg as a call to download.php?file=image.jpg

RewriteEngine On
RewriteRule ^(.*).jpg$ ../download.php?file=$1.jpg [L]

The 2nd example tells apache that all jpg files are really php files, and also tells php to run a php script first before php tries to handle the file. A kind of header code that you'd need to get the name of the jpg file in one of the $_SERVER variables.
@jmraker, oh that's pretty usefull. I'll get some practice with it tomorrow Smile
Related topics
Windows Vista Official 133 Icons download
Final Fantasy Tactics Advance
A Nice Magic Trick By My Friend
Stop Snitching
Redirecting my domain name?
Firefox turn off the design mode
Find Who is InVisible On Yahoo Messenger
Do you have habit to save money?
PHP Login Sessions & Security with Frihost
How to Rename the Recycle Bin
Ring finger straight up while little finger curled
Have you ever tried this out with your camera?
Firefox Addons Used
Reply to topic    Frihost Forum Index -> Scripting -> Php and MySQL

© 2005-2011 Frihost, forums powered by phpBB.