Marc
Marc

Reputation: 1184

Showing PDF's with blocking direct link (.htaccess)

I'm trying to show my PDF files in my webpages but block the direct access to the files. I'm trying to do this by using a .htaccess file like this:

order deny,allow
deny from all
allow from {MY_IP}

Where MY_IP is my server IP address (ex. 11.22.333.444), but when I do this my server can't access the files anymore. I'm showing the PDF's with this code:

    <object data="downloads/PDF/doc.pdf" type="application/pdf" width="100%" height="100%">

<p>It appears you don't have a PDF plugin for this browser.
You can <a href="doc.pdf">click here to
download the PDF file.</a></p>

</object>

The webpage just stays blank (it can't load it). Is there anything I'm missing with .htaccess?

Thanks for helping in advance!

Marc

Upvotes: 0

Views: 2031

Answers (1)

AbsoluteƵER&#216;
AbsoluteƵER&#216;

Reputation: 7870

You can check the referring website to see if it's your own with .htaccess

RewriteEngine On
RewriteCond %{HTTP_HOST}@@%{HTTP_REFERER} !^([^@]*)@@http?://\1/.*
RewriteRule .*\.pdf [NC,F]

That will fail with a forbidden directive (403 error). NC is case insensitivity. The server would need to be configured to show something in the event of a 403 error.

In PHP Additionally you can check this sort of thing with a dynamic page that allows the download. Here's an example of how to do this with PHP:

<a href='/download.php?f=myfile&fd=mypath'>Download my PDF</a>

We're taking the .pdf off of the name in the link for security reasons. You could do something like base64_encode the name, but this won't stop a knowledgeable attacker from trying to exploit your system. The f variable is the filename (pre-period) and the 'fd' would be the folder (or path).

Example dirs could include pdfs or resources/pdf.

It can't start or end with a /. We're not allowing periods in paths or filenames so someone can't do something like pdf/../../...

Code for download.php

<?php
if((preg_match('!^[A-Za-z0-9_-]+$!',$_GET['f']))&&(preg_match('!^[^/][/A-Za-z0-9_-]+[^/]$!',$_GET['fd']))){
//we're hard-coding the line so someone can't spoof something like .htaccess
$tempPath = $_GET['fd'];
    $tempFilename = $_SERVER['DOCUMENT_ROOT'].'/'.$tempPath.'/'.$_GET['f'].'.pdf';

    //Make sure it's a real file
    if(is_file($tempFilename)){
        $referrer = $_SERVER['HTTP_REFERER'];
        $serverName = $_SERVER['SERVER_NAME'];
        //check the referrer
        if(strpos($referrer, $serverName)){
            $new_filename = $_GET['f'].'.pdf';
            // We'll be outputting a PDF
            header('Content-type: application/pdf');

            // It will be called downloaded.pdf
            $hString = 'Content-Disposition: attachment; filename="'.$new_filename.'"';
            header($hString);

            // The PDF source is in original.pdf
            readfile($tempFilename);
        } else {
        //offsite link
        header('Location: /download_policy.php');
        exit(); 
    }
    } else {
        //maybe an old file? Give them the homepage
        header('Location: /');
        exit(); 
    }
} else {
    //hacking attempt
    header('Location: /');
    exit(); 
}
?>

Upvotes: 3

Related Questions