Protected File Download Script. Almost there - php

I have a file that users will purchase via paypal, clickbank and paydotcom. I have to host the file's download page on my server.
I've placed the file in a directory outside my public_html folder. The folder is on the same level as public_html and called "download" for example.
The script below is supposed to do that, but I have two problems with it...
1) It doesn't seem too secure. just check for a payment confirmation token on the querystring?
2) I can't the $path variable to point to the download folder without including my site.com public folder in the path. For example, when I echo $path, I get
/home/myuser/public_html/mysite.com
But I need it to resolve to
/home/myuser/download/myprotectedfile.zip
I'm sure there is a more secure or clever way to do this, so I'm asking...
<?php
// place this code inside a php file and call it f.e. "download.php"
$path = $_SERVER['DOCUMENT_ROOT']."/path2file/"; // change the path to fit your websites document structure
$fullPath = $path.$_GET['download_file'];
if ($fd = fopen ($fullPath, "r")) {
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-type: application/pdf"); // add here more headers for diff. extensions
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
break;
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
}
header("Content-length: $fsize");
header("Cache-control: private"); //use this to open files directly
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
exit;
// example: place this kind of link into the document where the file download is offered:
// Download here
?>
The problem I'm having in getting this to work is the the value of $path includes my site.com reference, but the download directory is outside site.com. I need to get a reference up a level in order to point to the directory that holds the download file.
Also, as I stated earlier, I'm not sure how to do this (other than checking for an expected querystring value in a manner that's secure)
Thanks in advance!

You can use the parent directory shortcut ../ in your $path or the dirname function like:
$parent_dir = dirname( dirname( __FILE__ ) );
// first dirname is the directory of this file, second goes up one level, etc.
BTW, beware of indicating the path in your URL, one could read other files (like configuration files or ohter private files) by changing it to download.php?download_file=../../private/bank_certificate.pem. You should use realpath to get the absolute path of the file and compare it to an "authorized for download" file list.

You just need to consider the path like a normal directory path, not a web one. so to go up a level simply "../" e.g.
if you structure is like this
/path2file/inhere.pdf
/public_html/download.php
the path to the file would simply be from download.php "../path2file/inhere.pdf"

well if public_html is your doc root then you should be able to get the path to download would be
realpath($_SERVER[DOCUMENT_ROOT].'/../download');

Custom coding may not be the best solution these days for a file download script. Check out Drupal which has file download modules, that can be integrated with its Clickbank module as well:
http://drupal.org/project/clickbank_ipn

Related

How to hide download file path from user using php?

When user want to download file from my web site, user have to click link like below
https://www.example.com/download.php?aaa=111&bbb=222
download.php
<?PHP
session_start();
include("connect.php");
$aaa = mysql_real_escape_string($_GET[aaa]);
$bbb = mysql_real_escape_string($_GET[bbb]);
if(($aaa = '111')&($bbb = '222')) // this line is example for ask stackoverflow //
{
$filePath_try_to_download = 'attachments_files/test.pdf';
if(file_exists($filePath_try_to_download))
{
$fileSize = filesize($filePath_try_to_download);
$fileName = "test.pdf";
header("Cache-Control: private");
header("Content-Type: application/stream");
header("Content-Length: ".$fileSize);
header("Content-Disposition: attachment; filename=".$fileName);
// Output file.
readfile ($filePath_try_to_download);
exit();
}
}
?>
I want to know when user download file from this link https://www.example.com/download.php?aaa=111&bbb=222 user can get my file path on server or not (attachments_files/test.pdf). If user can get my file path, how can i hide it's ? (file in this dir is very importance)
Since I was posting comments from my Phone, they couldn't really explain much, so here goes your answer.
I want to know when user download file from this link https://www.example.com/download.php?aaa=111&bbb=222 user can get my file path on server or not (attachments_files/test.pdf).
No, Users can not see that file path which you are reading via readfile(). They will not be able to find out that file's location at all.
And if you want to eliminate any chances of people guessing the file path simply put those files outside of your web root folder and then readfile() them from there.
$filePath_try_to_download = 'attachments_files/test.pdf';
That path is only known to your PHP code, which is not visible to users hence they have no idea from where did you read the file they are downloading, just eliminate the guesswork chances though :)
And Obviously you have to secure access to this url https://www.example.com/download.php?aaa=111&bbb=222 otherwise what's the point!
No. The user cannot get the file path. He only get the content outputed by PHP script.
Your can do this and the user only get the "Hello" string. So it's your PHP script's role determining which contents the user can get.
<?php
echo "Hello";
?>

I want a download that acts like a proxy

I want my users to download a file say file.zip
from
www.remoteurl/file.zip
but the file should be downloaded from
www.mydomain.com/file.zip
I want my server to act as a proxy which will change the remote url to mydomain. (Note: the file shouldn't be downloaded to my server.)
Can you suggest a good approach for this, or is there even a finished script for this purpose ?
Your question isn't very clear, still, I think you want users to think they're downloading a file from your server while in fact the download is located on a remote server. If my assumption is correct, there are many ways to achieve that, here's one:
Let's say the user clicks on a link that contains:
http://www.yousite.com/myfiles/file.zip
First, we use mod_rewrite to forward any requests to myfiles to our phpscript (download.php).
.htaccess
RewriteEngine on
RewriteRule ^myfiles/(.*)$ /download.php?file=$1 [NC]
Now we can $_GET the value of file inside download.php
download.php
if(!EMPTY($_GET['file'])){
$url = 'http://www.remoteurl.com/'.$_GET['file'];
$path_parts = pathinfo($url);
$ext = $path_parts['extension'];
$filename = $path_parts['filename'];
header("Content-type: application/$ext");
header("Content-Disposition: attachment; filename=$filename");
echo file_get_contents($url);
}
You might want to restrict the downloads based on the file extension, for that you can use:
if (!EMPTY($_GET['file']) && preg_match('/\.(zip|txt|rar|tar|gz)$/', $_GET['file'])) {
//the rest of the code...

zip file protection on server

I have zip files in my website and I made a log in system so only users with valid passwords can download the zip files ONCE.
But there is always a possibility that they can download the zip files directly by entering the file path in the browser address bar.
You can get the link of the zip file by viewing the source code.
How can I deny people from downloading zip files by simply posting the file link in the browser address bar? is possible?
Instead of placing the file in a web accessible folder (/var/www/ for example), place it above it so users can't browse to it (like /var/files). Then to serve it to your users, after they type the password, with a php script, have the script set the headers as they would if it were a file, and use readfile to output the contents of the file to the user.
Firstly, create a folder in your root (~/) called secure_zip or something. This should sit alongside your public_html folder (meaning they cannot be accessed by typing in a URL).
Next, create a new php script, called file.php or something:-
<?php
public function sendFile() {
$filename = "sample.zip";
$attachment_location = $_SERVER["DOCUMENT_ROOT"]
. "../secure_zip/" . $filename;
if (file_exists($attachment_location)) {
header('Cache-Control: public'); // needed for i.e.
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="' . $filename . '"');
readfile($attachment_location);
die();
} else {
die('Error: File not found.');
}
}
And call sendFile() if you authenticate the user using whatever logic you like, eg:
if (true) { sendFile(); }

I want to search a directory for multiple files using PHP and start a download them over HTTP

Just to start, I'm a PHP noob.
I have an Apache server which hosts my files. I have a device which can only point to one PHP file. What I need it to do is have my PHP file read in the name of the file I want to download, and point it towards the directory it is stored. Currently, I have it pointing to one file, but I need it to be able to point to multiple. Is this possible in PHP?
Here's what I have so far:
<?php
$file_name = 'file.img';
$size = filesize($file_name);
$file_url = 'http://192.168.0.5/' . $file_name;
header("Content-length: $size");
header("Content-Type: text/plain");
header("Content-Transfer-Encoding: binary");
header("Content-disposition: attachment; filename=\"".$file_name."\"");
readfile($file_url);?>
Edit:
The commands I want to input in order to download the file are close enough to as follows:
cmd=download+-a+$$.img+altimage
cmd=download+-a+$$.conf+altconfig
and the download directory is the .php file. I am open to other suggestions in how to do this.
Edit2:
Here's what an exact sample URL is:
myserver.com/cgi-bin/va/cmd?hdl+fullconfig.ini+altconfig
the hdl is a predefined function which points to the download directory, in order to download the file from the server, so the layout of what you mean isn't exactly the same.
I have trouble understanding what exactly you're trying to do, but I guess that you want a user to be able to download multiple files. If that is correct, here is one way to achieve this:
You can let PHP create a ZIP archive using the ZIP extension. For it to work, you have to load the extension php_zip.dll inside your php.ini.
$ZIP = new ZipArchive();
// Use the current time as the filename to prevent two users to use the same file
$ZIPName = microtime().".zip";
// Create a new ZIP file
$ZIP->open($ZIPName, ZIPARCHIVE::CREATE);
// Loop through all files - $Files needs to be an array with the names of the files you want to add, including the paths
// basename() will prevent the creation of folders inside the ZIP
foreach ($Files as $File) {
$ZIP->addFile($File, basename($File));
}
// Close the archive
$ZIP->close();
// Send the archive to the browser
readfile($ZIPName);
I hope this is what you were looking for.

PHP to protect PDF and DOC

I am trying to provide .pdf and .doc files to authorized users on a website. The user can only see the file selection page when logged in but this doesn't prevent an unauthorized user from viewing the documents if they have knowledge of the full URL.
How can I prevent unauthorized users from accessing these files?
the answer is quite simple,
#Jonnix has posted this as I was typing but I will explain a little more for you
one put your files outside of your public HTML directory if your unable to do this look at #Andri answer for an alternative
E.G cpanel setup
user/public_html
/public_html/download.php
user/documents/
/documents/file.doc
/documents/file.pdf
#dhh has posted a basic download.php php file however as your wanting to force download their things you can do like finding and supplying the correct mime type here is an extension on to his code as to the best way to 1 force download of a file, and 2 allow different file types
download.php
//check users is loged in and valid for download if not redirect them out
// YOU NEED TO ADD CODE HERE FOR THAT CHECK
// array of support file types for download script and there mimetype
$mimeTypes = array(
'doc' => 'application/msword',
'pdf' => 'application/pdf',
);
// set the file here (best of using a $_GET[])
$file = "../documents/file.doc";
// gets the extension of the file to be loaded for searching array above
$ext = explode('.', $file);
$ext = end($ext);
// gets the file name to send to the browser to force download of file
$fileName = explode("/", $file);
$fileName = end($fileName);
// opens the file for reading and sends headers to browser
$fp = fopen($file,"r") ;
header("Content-Type: ".$mimeTypes[$ext]);
// this header tells the browser this is a download and not to try and render if it is able to E.G images
header('Content-Disposition: attachment; filename="'.$fileName.'"');
// reads file and send the raw code to browser
while (! feof($fp)) {
$buff = fread($fp,4096);
echo $buff;
}
// closes file after whe have finished reading it
fclose($fp);
P.S here is a big list of mime types if you want to add support for other files
https://www.freeformatter.com/mime-types-list.html
What you can do, is provide the equivalent of a PHP proxy for the files.
Put the files outside of the webroot, then write a script that checks the user is allowed access. If not, redirect them, if they do, set the appropriate headers and output the file data.
You should store all downloads outside your public / user-accessable doc root (but inside your basedir, of course) and add a download script for sending the download if the user is authorized.
Here's some example of how to "send" a file for downloading it.
$file = "ireland.jpg";
$fp = fopen($file,"r") ;
header("Content-Type: image/jpeg");
while (! feof($fp)) {
$buff = fread($fp,4096);
print $buff;
}
This did the job for me: I placed a .pdf and a .htaccess file with the following code in it in a normal folder (i named it "docs") on my apache webserver.
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
<Files /index.php>
Order Allow,Deny
Allow from all
</Files>
Then i took the code from Martin Barkers answer above, changed the filepath to "docs/sample.pdf", and pasted it into a .php file in my root directory. That's it. You can't access the file per url now, but you can download it if you run test.php.

Categories