How to serve documents from outside the web root using PHP?
I think something like this would work:
<?php
$path = realpath(dirname(__FILE__) . '/../my_files/' . $_GET['file']);
$parts = explode('/', pathinfo($path, PATHINFO_DIRNAME));
if (end($parts) !== 'my_files') {
// LFI attempt
exit();
}
if (!is_file($path)) {
// file does not exist
exit();
}
header('Content-Type: ' . mime_content_type($path));
header('Content-Length: ' . filesize($path));
readfile($path);
Serving documents outside the web root folder.
readfile is used with the parameter of a file name - NOT text.
Two examples that would work (file_get_contents):
public function viewDoc($doc) {
$path_parts = pathinfo($_SERVER['REQUEST_URI']);
$file = $doc;
$fileDir = '/var/uploads/';
$filePath = $fileDir . $file;
if (file_exists($filePath))
{
$contents = file_get_contents($filePath);
header('Content-Type: ' . mime_content_type($filePath));
header('Content-Length: ' . filesize($filePath));
echo $contents;
}
}
or (readfile):
public function viewDoc($doc) {
$path_parts = pathinfo($_SERVER['REQUEST_URI']);
$file = $doc;
$fileDir = '/var/uploads/';
$filePath = $fileDir . $file;
if (file_exists($filePath))
{
header('Content-Type: ' . mime_content_type($filePath));
header('Content-Length: ' . filesize($filePath));
readfile($filePath);
}
}
I also added the $filePath
variable for you, as there's no reason to concat the string multiple times.
Edit
As extra security, to Yazmat's comment, you can use $file = str_replace(array('..', '/'), '', $doc);
as this would remove all references to other directories (however, with the slash it would also remove access to sub directories, so you might want to skip that, dependend on your code and file structure).
PHP - Security in accessing files outside of web root
You need to allow Apache (assumed) to access that folder with images using Directory directive (http://httpd.apache.org/docs/2.2/mod/core.html#directory).
Or you can move images under root directory and restrict direct access to them using .htaccess if you want to keep them protected.
Serving images from outside of document root
The most common way is an Alias:
Alias /data/ /wherever/your/data/are/
Access a file which is located before / outside the server root directory?
You cannot directly access any file outside your web directory. As your question includes the tag PHP as well, I assume you may want to use it.
What you can do is the following:
Inside your www directory, create a "image.php" file, with a similar content to:
<?php
header('Content-Type: image/png');
readfile("../img/" . $_GET['img']);
?>
And call your images with
<img src="image.php?img=myimage.png" />
Please be aware that your PHP file shouldn't be that simple :) As you may want to address multiple image formats (and providing the correct header for them), checking for malicious file path/inclusions (you don't want to use $_GET without validating/sanitizing the input), extra caching etc. etc. etc.
But this should give you an idea on how you can target your issue.
How to serve a video from a file outside the web root in PHP to a html5 video source
Your code looks correct, and when I've just tested a very similar script, it has worked perfectly.
A couple of thoughts:
- Have you tried accessing your video script (serve_movie.php) directly within your browser to see if you get the video?
- Do you have error reporting turned on, and set to display errors? If so, are you getting any? I'm wondering if reading in the content of your video is exhausting PHP's memory limit due to its size.
To enable error reporting, add the following to your video script (serve_movie.php) before any other code:
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('html_errors', true);
Downloading files outside the webroot
After much trial and error, I appear to have solved the problem.
The issue was in using jQuery/Ajax.
When I changed the way the downloadscript.php
file is accessed to a direct $_GET
request from the link on the page, it worked a treat.
Anyway, thanks for your help everyone!
Chris
PHP include file in webroot from file outside webroot
Full path should be:
include('/home/xx/xx/domains/mydomain/webroot/file-to-include.php');
Or you should set the path like:
include(__DIR__ . '/../webroot/file-to-include.php'); // php version >= 5.3
include(dirname(__FILE__) . '/../webroot/file-to-include.php'); // php version < 5.3
How to upload a file to a folder outside web root
By default files will be uploaded well above the web root for security and you have to move them to wherever you want. Take a look at move_uploaded_file().
Have a look at print_r($_FILES)
and it will show you the location of each file you have uploaded.
Related Topics
Retrieve Data from Db and Display It in Table in PHP .. See This Code Whats Wrong with It
PHP and Microsoft Access Database - Connection and Crud
PHP Datetime Round Up to Nearest 10 Minutes
Datetime Class VS. Native PHP Date-Functions
Android Post Base64 String to PHP
How to Correctly Link PHP-Fpm and Nginx Docker Containers
Get Characters After Last/In Url
After Array_Filter(), How to Reset the Keys to Go in Numerical Order Starting at 0
Which Coding Style You Use for Ternary Operator
Split a Text into Single Words
Jquery Mobile: Sending Data from One Page to the Another
PHP Localization Best Practices? Gettext
Pdo: Invalid Parameter Number: Mixed Named and Positional Parameters
Foreach Value from Post from Form
PHP Web Scraping of JavaScript Generated Contents
Practical Zend_Acl + Zend_Auth Implementation and Best Practices