As John H. suggested earlier, storing files outside ("above") the webroot makes those 
files inaccessible directly from the user's
browser-- a good thing-- in which case the script serves as a gateway to these files-- 
also a good thing.

I have a similar need. Here's one way to do it in two steps. This is written without 
classes in mind-- I'm sure my code could be
made more elegant (I'm learning, too).

Step 1: Present the user (who's being authenticated throughout the process) a web page 
listing the files with links to each. To
prepare the links, the script reads through the files in the protected directory 
placed above the webroot.

////// open directory (which is placed above the webroot)  & read files into an array 

// Set $course_content_path to the desired directory outside the webroot

$myDirectory = opendir("$course_content_path/download");

 // get each entry
while ($file = readdir($myDirectory))
if ($file != "." && $file != ".." && $file != "index.htm" && $file != "index.html") // 
strip ., .., & index files from dir listing
        $dirList[count($dirList)] = $file; // assign each file to the array
 //Clean up and sort

////////// process $dirList to get to the file names and file extensions 
$num_elements = count($dirList);

for ($i = 0; $i < $num_elements; ++$i){ // loop through $dirList

$str = $dirList[$i];
$pattern = ".";
$filename_parts = explode(".", $str); // split file name into a two-element array

// this intermediary step probably not necessary-- "If I'd had more time, I'd have 
written a shorter letter"
$file_name[] = $filename_parts[0];
$file_extension[] = $filename_parts[1];

$file_info[$i][0] = $file_name[$i];
$file_info[$i][1] = $file_extension[$i];

// Now we can loop through $file_info array to build the filenames and file types into 
the links. Clicking on a link calls the
following function show_file().

// Step 2: When a user clicks on a link to a file, the function show_file() sends the 
file to the browser.

function show_file(){
// whatever globals
// $f = the filename.fileextension user wants. $f built into URL link.

print "Error: This page called incorrrectly.\n";

$pattern = ".";
$filename_parts = explode(".", $f);
$file_name = trim($filename_parts[0]);
$file_extension = trim($filename_parts[1]);

// limit the valid file types

if($file_extension != 'doc' && $file_extension != 'htm' && $file_extension != 'html' 
&& $file_extension != 'wps' && $file_extension
!= 'rtf' && $file_extension != 'gif' && $file_extension != 'jpg'){
print "Error: $file_name.$file_extension file type called incorrrectly.\n";

// validate for alphanumeric file name or whatever file naming convention you use

if(!eregi("^[a-zA-Z0-9_]+$",$file_name)){ // is file name non-alphanumeric?
print "Error: Incorrect file name.\n";

// read file into variable $file_output

$file_output = fopen("$course_content_path/download/$f","r");
if(!$file_output) die("Cannot open $f<br>");

// use fpassthru to pass file to the browser. Test for file type to send appropriate 

if($file_extension == 'doc' || $file_extension == 'rtf'){
header("Content-type: application/msword");
header("Content-Disposition: attachment; filename=$f");

if($file_extension == 'htm' || $file_extension == 'html' || $file_extension == 'gif' 
|| $file_extension == 'jpg'){
header("Content-type: text/html");
header("Content-Disposition: inline; filename=$f");

if($file_extension == 'wps'){
header("Content-type: application/msworks");
header("Content-Disposition: attachment; filename=$f");

}  // end function show_file() //

If you're tracking the user through his or her session, then passing the file through 
the script lets you track which users are
viewing or downloading which files as well as regulating access to those files.

For whatever all this is worth....

All the best,

Steve Overall

----- A Previous Reply to Original Message -----
Store your files outside of the webroot if you use this method. Then
they can't type in the address directly (otherwise this doesn't fix

---John Holmes...

----- Original Message -----
From: "Nick Wilson" <[EMAIL PROTECTED]>
To: "php-general" <[EMAIL PROTECTED]>
Sent: Saturday, May 11, 2002 1:58 AM
Subject: [PHP] protecting downloads with php

> Hash: SHA1
> Hi all
> I've been asked to protect an area containing 'course material' (pdf's
> etc) and have just thought of a gaping hole in what I've done.
> I use an class to handle all the auth stuff and each page checks the
> value of $obj->logged_in :: No problem.
> but what if someone links to www.thesite/theProtectedArea/file.tar.gz
> that file cannot check if the downloader is logged in can it.
> So, any suggestions or words of wisdom would be much appreciated :-)
> - --
> Nick Wilson     //
> Version: GnuPG v1.0.6 (GNU/Linux)
> iD8DBQE83N09HpvrrTa6L5oRAlSZAJwNVHXfeP3w8aaJTtRUmPH2v/nvNwCfaqp4
> HpXVvWLn87rkhCQxnBtszAc=
> =St/c
> --
> PHP General Mailing List (
> To unsubscribe, visit:

PHP General Mailing List (
To unsubscribe, visit:

Reply via email to