Protect Downloadable Files on server? - php

like if some attempts to download a files .zips
eg. http://usb-drive/src/Members.jpg
i don't want to bother with this AuthType Basic using apache or the PHP version..
<Directory "/src/Members.jpg">
AuthType Basic
AuthName darkness
AuthUserFile /usr/www/
AuthGroupFile /usr/www/
require valid-user
</Directory>
then pop up login box appears….Authentication required!
i just want to direct them away to a php page instead, and handle all auth stuff via PHP
can the apache rewrite mod directives do that?

Readfile is the function you need, you can then do something like:
<?php
$file = 'thefile.zip';
if ( permissionCheck() === true) {
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
} else {
echo 'You do not have permission to view this file';
}
You can then keep the files outside the public webroot, so they can't be accessed directly and just read them out with PHP when you want to expose them.

Related

How to redirect a pdf GET request through a php script in wordpress with OpenliteSpeed Server

I have built a functionality on my website where I only want to allow certain people to be able to download or access certain pdfs from my uploads folder.
Searching aroud the internet and SO, I found a lot of answers and got really close in solving my problems.
The way I have structured my pdf is inside.
[root]/wp-content/uploads/scopes/unlocked-scopes/<filename>.pdf
I am interested in routing all the request for these files through a PHP script which is as follows.
<?php
require_once($_SERVER['DOCUMENT_ROOT'].'wp-load.php');
function manage_action()
{
$page = get_permalink( get_page_by_path( '404-not-found' ) );
if($page) {
wp_redirect( $page );
exit();
} else {
wp_redirect(home_url());
exit();
}
}
// Bail if request paramter doesn't exist.
if(!isset($_GET['request'])) {
manage_action();
}
// check if someone is logged in or not.
if( !(current_user_can('author') || current_user_can('administrator')) ) {
manage_action();
}
// Get Scope
$scope_exists = get_posts( array(
'post_type' => 'project_scope',
'p' => $_GET['request'],
'numberposts' => 1,
));
// Bail if scope doesn't exists.
if(empty($scope_exists)) {
manage_action();
}
$scope = $scope_exists[0];
$author = $scope->post_author;
$user = get_current_user_id();
if(!current_user_can('administrator') && ($user != $author)) {
manage_action();
}
$file = wp_upload_dir()['basedir'] .'/scopes/unlocked-scopes/'.$_GET["file"];
if(substr($file, -1) == '/') {
$file = substr($file, 0, -1);
}
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
Initially I built this restriction on my Local machine with Laragon setup on my windows machine and using Apache server.
I added the following in my .htaccess files at the root.
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} (unlocked-scopes.*)
RewriteRule ^wp-content/uploads/scopes/unlocked-scopes/(.*)$ wp-content/uploads/dl-file.php?file=$1 [QSA,L]
</IfModule>
This works absolutely fine on apache local server, but my live server is using openlitespeed server on a digital ocean droplet and it doesn't work there at all.
I have added this rule before the wordpress rule.
UPDATED
When I try to visit any pdf from unlocked-scopes folder in my live server it opens without ever hitting my php script which makes it accessable publically. Is there something else that needs to be added when working with openlitespeed and .htaccess ?
I was able to find the documentation which talks about the migration of Rewrite rules from apache to openlitespeed server.
The Article
In the documentation part "Migrate from Apache Document Root .htaccess to OpenLiteSpeed Vhost Rewrite Tab" it is said that,
RewriteRule ^adminPages/(.*)$ admin-panel/$1 [L]
Changes to
RewriteRule ^/?adminPages/(.*)$ admin-panel/$1 [L]
this.
And I had to add it inside OpenLiteSpeed (Webadmin panel.) > VirtualHost > Edit your host > Rewrite tab.
Webadmin panel by deafult is at 7080 port.
My final Rewrite rule was.
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_FILENAME} (unlocked-scopes.*)
RewriteRule ^/?wp-content/uploads/scopes/unlocked-scopes/(.*)$ wp-content/uploads/dl-file.php?file=$1 [QSA,L]
</IfModule>
And I added it inside the rewrite tab.

Php: How to protect images for downloading [duplicate]

This question already has answers here:
Protect image download
(17 answers)
Closed 6 years ago.
In my site we are doing image protecting section. Can I protect images in my site from others without download.That is i want to protect my image from downloading by others.Is it possible using php code
you can do this by using force download in php.
$file_url = 'base path to file / file name';
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"" . basename($file_url) . "\"");
readfile($file_url);
this code will download the file and block files folder using htaccess
<IfModule authz_core_module>
Require all denied
</IfModule>
<IfModule !authz_core_module>
Deny from all
</IfModule>

Output 3gp audio/video in php

I have a problem that I can not solve.
I use RewriteEngine in my .htaccess to access some videos. I need to export them for use in android.
My .htaccess:
RewriteRule ([^/]*)\.amr$ api.php?cmd=getmp3&hash=$1 [L]
In api.php
$__GB->getSafemp3($_GET['hash']);
And feature code:
header('Content-Type: video/3gpp');
header('Content-Disposition: inline; filename=' . $fetch['new_name']);
header('Content-length: '.filesize($path));
header("Content-Transfer-Encoding: binary");
readfile($path);
With the URL directly works perfectly, but not RewriteRule
Edit:
I've fixed the problem, i changed the feature code for this:
header('Location: ' . $path.$fetch['new_name']); //$path.$fetch['new_name'] is the file directory, ex: /music/audio.3gp

How to calculate time with a php force download script?

I have a rather simple force download script:
$thefile = $_GET['id'];
$file = 'http://www.mywebsite.com/test/'.$thefile;
header('Content-Disposition: attachment; filename='.$thefile);
header("Content-Type: application/force-download");
#readfile($file);
And it works nicely, except it does not show how much time is remaining ("could not calculate time").
I found someone with a similar problem here, by using this code:
# for URL paths that begin with "/foo/bar/"
SetEnvIf Request_URI ^/foo/bar/ no-gzip=1
# for files that end with ".py"
<FilesMatch \.py$>
SetEnv no-gzip 1
</FilesMatch>
But alas, I can not get that to work. My files are media files (avi, wmv, mp4 and so forth), so I assumed I would have to modify the code along these lines:
SetEnvIf Request_URI ^/test/ no-gzip=1
<FilesMatch "\.(avi|wmv|mp4|mpg|mpeg|m4v)$">
SetEnv no-gzip 1
</FilesMatch>
I have also changed the path to a simple test folder, but time is still not being displayed.
How to?
You should add content-length header, for your browser to know total file size.
header("Content-Length: " . filesize($file));
Take a look at this example.

X-SendFile on Apache2 (PHP) serving 0B file, no errors though

I installed mod_xsendfile and it seems to have been successful; xsendfile.load appears in /etc/apache2/mods-enabled, and I've found no errors when running my test script. However, every time I run it, I get served a 0B file.
Here's my test script:
$file = 'sample.mp4';
$path = '/var/storage/media/'.$file;
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header("Content-type: application/octet-stream");
header("X-Sendfile: $path");
Obviously I have a file stored in /var/storage/media/sample.mp4, it's only 25MB, and is served perfectly fine if I do it this way:
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($path));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($path));
ob_clean();
flush();
readfile($path);
exit;
I also have this in the .htaccess file of both /var/storage and /var/www (the files that has all this is stored in /var/www/files/index.php):
XSendFile on
XSendFileAllowAbove on
Like I said, I get no errors, and the PHP can certianly access the file, but I must be missing something with the x-sendfile configuration... that reminds me, I notice in mods-enabled just about every mod has a .load and .conf, but xsendfile only has .load, but so do a few others, so would that have anything to do with it?
Thanks.
I had the same problem and this solution worked for me:
After installing the module, you need to enable it and give an access path into the Apache configuration (httpd.conf for global configuration, or specific site vhosts for specific configuration) like these:
# enable xsendfile
XSendFile On
# enable sending files from parent dirs
XSendFilePath /var/www/
Of course you must replace /var/www/ by whatever folder you want xsendfile to have access to
Make sure you also turn on XSendFile in your Apache configuration if using Apache. If you don't do this, it will look like it works, but empty files will be served.
For example:
<Directory /var/www/>
Options Indexes FollowSymLinks MultiViews
XSendFile on
AllowOverride All
Order allow,deny
allow from all
</Directory>
I'm using it on Ubuntu 14.04 and Apache/2.4.7.
It's important to:
Setup on each host configuration:
<Directory /var/www/path/to/files>
XSendFile On
XSendFilePath /var/www/path/to/files
</Directory>
Add to .htaccess:
XSendFile on
While I was using only 1; it kept me downloading empty files.
After adding 2, worked nicely.
On Windows I had to use the following in order be able to serve files outside of doc roo.
Everything else was giving me 404
XSendFilePath C:/
Try making header("X-Sendfile: $path"); the first header() call in the file.
Also take a look at this. Seems like a similar issue and it may give you some ideas:
X-Sendfile Error

Categories