views:

91

answers:

1

Hi everybody,

actually I'm trying to pass referers inside the .htaccess. What I'm trying to do is that the referer value shall be send to a PHP script where this value will be saved to a databse. In some cases (depending on the referer) the image shall be blocked (hot linking) and in some other cases the image shall be shown normally. But it will not work :-( My current "try" looks like the following (it is just for testing, so currently every image will be handled):

RewriteCond %{REQUEST_URI} (.*)jpg$
RewriteCond %{ENV:verified}  ^$  
RewriteRule (.*)jpg$   /include/referrer.php?ref=%{REQUEST_FILENAME}&uri=%{REQUEST_URI}&query=%{QUERY_STRING}&env=%{ENV:verified} [E=verified:yes]

RewriteCond %{REQUEST_URI} (.*)jpg$
RewriteCond %{ENV:verified} ^yes$
RewriteRule ^(.*)$    %{REQUEST_FILENAME} [E=verified:no]

The referrer.php look like:

<?
 log_img($_REQUEST['uri'].' - "'.$_REQUEST['env'].'"');
?>

The problem is that the referrer.php is called but the image will not be displayed, which is obvious because the second rule is not reached.

I also have tried to display the image inside of the referrer.php, like:

<?
 log_img($_REQUEST['uri'].' - "'.$_REQUEST['env'].'"');
 $src = str_replace($_SERVER['DOCUMENT_ROOT'],'',$_REQUEST['ref']);
?>
<img src="<? echo $src ?>" />

But then the .htaccess is called again and I will run into endless loops.

The question is now: how can I access the second rule or how can I achieve what I want to do. Is there any way to do that?

Thanks for your help, Lars

A: 

Your current solution doesn't work because mod_rewrite can only be used to rewrite the request to a single destination, but you seem to want the request to take a detour to your PHP script, then continue onward to the image. It might be possible to cause a subrequest that would cause the PHP script to get triggered, but I don't think it would be possible to control whether or not the original request continued on to the image in that scenario.

The best course of action here is to have your PHP file print out the actual image data (not an image tag referencing the image) after it does whatever checking/logging you intend it to do. You can do this with readfile(), provided that you send the right headers. After making sure the file is one of the images you want to serve up (and not some arbitrary file on your system...), you'll at least need to determine the appropriate content type, then print out the data. It's also a good idea to take caching (see this answer, as well as this one) into consideration.

Combining some of the techniques mentioned, a simple pseudo-example of the referrer script would be as follows. Note that you should research the best way to implement the techniques described, and you need to pay particular attention to security since you're opening files and printing their contents.

$filename = /* sanitized file name */;

log_img(/* log some data about the request */);

if (file_exists($filename) && allowedToView($filename)) {
    // Assume we're not on PHP 5.3...
    $types = array(
        'gif' => 'image/gif',
        'png' => 'image/png',
        'jpg' => 'image/jpg',
    );
    $parts = pathinfo($filename);
    $ext   = strtolower($parts['extension']);

    if (array_key_exists($ext, $types)) {
        $mime = $types[$ext];
        $size = filesize($filename);
        $expires  = 60 * 60 * 24 * 30;

        if (!empty($_SERVER['IF-MODIFIED-SINCE'])) {
            $modified = filemtime($filename);
            $cached   = strtotime($_SERVER['IF-MODIFIED-SINCE']);

            if ($modified <= $cached) {
                header('HTTP/1.1 304 Not Modified');
                exit();
            }
        } 

        header("Content-Type: $mime");
        header("Content-Length: $size");
        header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires)
            . ' GMT');
        header('Cache-control: private, max-age=' . $expires);
        readfile($filename);
        exit();
    }
}

header("HTTP/1.0 404 Not Found");
exit();

And as far as the .htaccess file goes, it would just be something like this (the stuff that you added to the query string is available in $_SERVER anyway, so I see no point in manually passing it to the script):

RewriteEngine on

RewriteRule \.(jpg|png|gif)$ /include/referrer.php [NC]
Tim Stone