Hi everyone,

I'm stuck on the best way to handle this. In a nutshell, I'm creating a website that sets up forums between one or several parties. Each participant of a forum can upload file attachments to any message they post.

What I want is a way to protect those uploads from being downloaded by non-authorized parties. The way it works now, I have a script that takes the forumID and the messageID, checks to make sure the user has access to the forum, and if so, returns the file to them for download. The problem however, is that if someone knows the file path "ex - user_data/forums/2400/filename.ext", they can grab it from there.

I don't want to have to make the user type in their username/password again in order to access the file, as is the case if I used .htaccess and .htpasswd....at least that I know of.

Anyone have suggestions?

EDIT: I guess I should caveat that by saying...a way OTHER than placing documents above the web root :)

ok found this on another forum. you might be able to work with it. you can also do a surch for (hide download url php script)

<?php
// Usage: <a href="download.php?file=test.txt&category=test">download</a>
// Path to downloadable files (will not be revealed to users so they will never know your file's real address)
$hiddenPath = "secretfiles/";

// VARIABLES
if (!empty($_GET['file'])){
$file = str_replace('%20', ' ', $_GET['file']);
$category = (!empty($_GET['category'])) ? $_GET['category'] . '/' : '';
}
$file_real = $hiddenPath . $category . $file;
$ip = $_SERVER['REMOTE_ADDR'];

// Check to see if the download script was called
if (basename($_SERVER['php_SELF']) == 'download3.php'){
if ($_SERVER['QUERY_STRING'] != null){
// HACK ATTEMPT CHECK
// Make sure the request isn't escaping to another directory
if (substr($file, 0, 1) == '.' ¦¦ strpos($file, '..') > 0 ¦¦ substr($file, 0, 1) == '/' ¦¦ strpos($file, '/') > 0){
// Display hack attempt error
echo("Hack attempt detected!");
die();
}
// If requested file exists
if (file_exists($file_real)){
// Get extension of requested file
$extension = strtolower(substr(strrchr($file, "."), 1));
// Determine correct MIME type
switch($extension){
case "asf": $type = "video/x-ms-asf"; break;
case "avi": $type = "video/x-msvideo"; break;
case "exe": $type = "application/octet-stream"; break;
case "mov": $type = "video/quicktime"; break;
case "mp3": $type = "audio/mpeg"; break;
case "mpg": $type = "video/mpeg"; break;
case "mpeg": $type = "video/mpeg"; break;
case "rar": $type = "encoding/x-compress"; break;
case "txt": $type = "text/plain"; break;
case "wav": $type = "audio/wav"; break;
case "wma": $type = "audio/x-ms-wma"; break;
case "wmv": $type = "video/x-ms-wmv"; break;
case "zip": $type = "application/x-zip-compressed"; break;
default: $type = "application/force-download"; break;
}
// Fix IE bug [0]
$header_file = (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) ? preg_replace('/\./', '%2e', $file, substr_count($file, '.') - 1) : $file;
// Prepare headers
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public", false);
header("Content-Description: File Transfer");
header("Content-Type: " . $type);
header("Accept-Ranges: bytes");
header("Content-Disposition: attachment; filename=\"" . $header_file . "\";");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($file_real));
// Send file for download
if ($stream = fopen($file_real, 'rb')){
while(!feof($stream) && connection_status() == 0){
//reset time limit for big files
set_time_limit(0);
print(fread($stream,1024*8));
flush();
}
fclose($stream);
}
}else{
// Requested file does not exist (File not found)
echo("Requested file does not exist");
die();
}
}
}
?>

Thanks for the code; I may implement a form of that in as well, but I'd like to actually protect the files themselves, just in case someone finds out where they are stored. I think I may use .htaccess and see if I can't loop back to my existing script with that.

you could always password protect the directory they are stored in, that way if someone finds out where they are they will need a password. you should be able to put a password on the directory from your webhost control panel

This article has been dead for over six months. Start a new discussion instead.