Protect a folder by .htaccess RewriteRule to php

We are building an online photo-album. People need to login to see the images.We are trying to protect the image-files as well but we are stuck in a problem

By a session-variable we check if the users is logged in.

$_SESSION['is_ingelogd'] 

We build a security page (which checks if the user is logged in). We include this page to every page that has to be secured. But now we want to protect the images too.

So we build a .htaccess file that refers all requests of files in our photo-folder to a php page. The php page has to check if the user is loged in. If the user is not loged in, it will echo a text with the request to login. If the user is logged in, the the php file has to to send the requested file (image).

We use the following code to do this:

The .htaccess file (in the folder /fotoalbum/uploads/ ) :

RewriteEngine On
RewriteBase /fotoalbum/
RewriteCond %{SCRIPT_FILENAME} !image\.php
RewriteCond %{REQUEST_URI} !image\.php
RewriteRule ^(.*)$ image.php [QSA,L]

The .php file (in the folder /fotoalbum/ ) :

<?php
session_start();

if ($_SESSION['is_ingelogd'] == "1") {
    $type = mime_content_type((string)$_SESSION['REQUEST_URI']);
    header("Content-type: ".$type);
    echo file_get_contents($_SESSION['REQUEST_URI']);
    exit;
} else{
    echo 'Please <a href="">login</a> to see this  
file.';
}

?>

This code works halves; If a user is not loged in and tries to open any file of the folder /fotoalbum/uploads/ , the php shows the request to login.

But if the user is logged in, we don't see the picture. In IE9, the screen keeps blank and in FireFox 3.6, a png returns a message that the image can't be
displayed because it contains errors. a jpg returns the url of it and a txt file returns 

We build this scripts with help of following links:

  • (#post 12)

Thanks for any help


UPDATE:

I did some prototyping and the return of mime_content_type((string)$_SESSION['REQUEST_URI']); seems to be blank/null.

I placed following code in the php file:

<?php
$serveruri = parse_url($_SERVER['REQUEST_URI']);
$fileuri = (string)('./uploads/'.basename($serveruri['path']).PHP_EOL);
$file = strval($fileuri);

echo 'URL Is: '.$file;  
echo '<br />type Is: '.mime_content_type((string)$file);
exit;
?>

The browser shows:

URL Is: ./uploads/test.jpg
Type Is: 

You can see it doesn't echo a content type. But when I set

$file = './uploads/test.jpg';

it perfectly returns:

URL Is: ./uploads/test.jpg
Type Is: image/jpeg

Any suggestion?


ANSWERS:


With many tips of this topic I made it work. However it works now with a query string in the URL.

.htaccess file in the folder fotoalbum/uploads/ :

Options -Indexes
<Files *>
  deny from all
</Files>

getfile.php file in the folder /fotoalbum/ :

<?php

//this file checks if user is logged in and dies the request if the user is not logged in
include_once('./config.php');

$file = "uploads/" . $_GET['f'];
$type = mime_content_type($file);

header("Content-type:" .$type);
echo file_get_contents($file);

?>

To get an image (or whatever type of file), the url is getfile.php?f=file.extension (where file.extension is the file in the folder fotoalbum/uploads/ .

Thanks al lot everybody for your help!


Hi I'm taking a shot here, but have you checked to make sure mime_content_type is returning the correct mime type for your file? It would seem like if the statement

header("Content-type: ".$type);

is not outputting correctly, then the image or text file will not come through correctly either. PHP.net indicates that the mime_content_type function is deprecated, so you might want to try out the finfo_file function.

Good Luck!


I guess the PHP-File is saved with BOM, save it without BOM.

Why i guess this:  looks like a BOM


You should use readfile() instead of echo file_get_contents() when streaming images and other binary files back to the client.

Update:

The issue you are having with mime_content_type() is due to PHP_EOL which is adding a line break. There also is a lot of unnecessary type casting. Below is a cleaned up version that should work for you:

<?php
$serveruri = parse_url($_SERVER['REQUEST_URI']);
$file = basename($serveruri['path']);


echo 'URL Is: ' . $file;  
echo '<br />type Is: ' . mime_content_type($file);

exit();
?>


 MORE:


 ? Use PHP to Dynamically Add To .htaccess File?
 ? Using htaccess to check file in another directory
 ? Protect files with .htaccess from the outside, while still allowing internal access
 ? how to Protect Php file with the htaccess to protevent external use or a direct use
 ? Re-writing Dynamic URL with .htaccess
 ? Spoof .php as .png in .htaccess?
 ? PHP: Handling Dynamic File Request
 ? How do you add dynamic 'where' clauses to a linq query?
 ? How do you add dynamic 'where' clauses to a linq query?
 ? How do you add dynamic 'where' clauses to a linq query?