Display images on site from folder outside public_html folder - php

I am using codeingiter and had a image directory in it. Due to space issue I have shifted the entire directory to new location on same server.
Earlier path was /var/www/html/site_folder/assets/images
New Location is /home/new_site/images
Now when I want to display images on web site its not getting load.
I have tried using the below code
$file = '/home/new_site/images/3.jpg';
header('Content-Type: image/jpeg');
echo "<img src='".readfile($file)."' &glt;";
I have approximately 50 images and I want to load them on my site.
This works on local but not on server. I am using Linux on local and Centos on server.

You are mixing things up. What you want to do is to return the content of the image file, but you return an HTML fragment.
There are multiple solutions you could try:
Create a symbolic link to the new image directory, most things could stay as they are. This migth or might not work depending on your web server configuration.
Change all the references to images from
src="image5.jpg"
to something
src="image.php?name=image5.jpg"
Then you need the script "image.php" which takes the name of the image as a query parameter and then returns the content:
<?php
// take care to make some clever checks here
// otherwise you introduce a security nightmare
$file = '/home/new_site/images/' . htmlspecialchars($_GET["name"]);
header('Content-Type: image/jpeg');
readfile($file);
?>

Related

php don't show images on second virtual host

I have an apache2 server with 2 virtual hosts defined (with same options):
- first is the production one, on www.domain.com, which works fine
- second is the development one, on dev.domain.com, which works almost fine, except that images returned by php doesn't show.
Images directly linked to files (img src or css) work fine.
The function to show images is quite simple :
$data = $this->image_model->get_image_blob($id);
header('Content-Type: image/jpeg');
echo $data;
At first, I thought there was a problem with data, but no, if I read data from an actual jpeg file, it doesn't show either.
An interesting thing is that if I create an image from data with :
$im = imagecreatefromstring($data);
imagesx and imagesy return correct image size.
But I still can't display the image. And there is no error.
Any idea about what happens?

Protect image contents from unauthorised people

We all know, this is a very important issue for many web developers. They want to protect direct access or direct readability to their confidential images. The folder that contains all the images is open and anyone can visit that folder, but I want to do something that can protect my image contents, means, if an unauthorised guy looks for an image he may get the image by visiting the appropriate folder but the contents will be invisible or difficult to understand. I think if I get a solution here, many guys will be helped from this question. Writing .htaccess isn't always a stable choice. So, after brainstorming I found some ways how I can protect image contents from direct access. I want to use Imagick with PHP to perform any kind of image editing.
Adding and removing a layer: After uploading, add a layer to make contents of the image invisible. So, if anyone reaches the folder you've stored the images will be meaningless as he will see the layer not the image content. Then remove the layer and show to them who have proper rights.
Converting the image to another format: Convert the image to any format like .txt, .exe, .bin, .avi or any other format so that without editing, the image won't be visible. Convert back to show it to the authorised user.
Image grid: Divide the image into some grids, say, if the image is medium 100 grids and change the position of the grids to make the contents unclear. To do this, we can name each grid like 1, 2, 3 and so on, then change the position to $position - 20. So the grid of position 25 will go to 5, 100 will go to 80, 1 will go to 81 and so on. Reverse the same way to display to the authorised users.
It is never possible to protect completely but we can make it harder. I don't know which of the three is possible with Imagick and which is not. Please tell me if you know. Thanks in advance.
You can put these images in a different folder outside of the public_html (so nobody can access them). Then via script, if a user is logged in, you get the image file content and then change the header. If a user is not logged, you can display a random image or showing a default image.
for example, the public html folder is: /var/www your image folder can be: /registered_user/images/
Then in your PHP script you can write:
<?php
if(!userLogged() || !isset($_GET['image'])) {
header('Location: /');
die();
}
$path = '/registered_user/images/';
$file = clean($_GET['image']); // you can create a clean function that only get valid character for files
$filename = $path . $file;
if(!file_exists($filename)) {
$filename = '/var/www/images/bogus.jpg';
}
$imageInfo = getimagesize($filename);
header ('Content-length: ' . filesize($filename));
header ('Content-type: ' . $imageInfo['mime']);
readfile ($filename);

PHP: set image as background without revealing path

The following problem I can't really wrap my mind around, so really if you guys can't be bothered to supply the entire code some tips leading in the right direction would be great!
So, I have a script where users can upload images to a server. PHP takes care of validating the file and saving it using a new filename in another folder, neither known by the client. Now, the client should be able to see the uploaded image, in html simply:
style="background-image:url('testimagegif.gif');
But preferably the client should not be able to see the path nor the file name of the image saved on the server. I know about using header('Content-type: ... for forcing the client browser to download files, but I do not see how this, nor any similar solution could be applied to this case. Same goes for readfile. If I use it the browser simply downloads the image, not placing it in the html.
You should probably be moving the files into a publicly readable folder on your webserver if you want to serve them.
Otherwise, you'll need something like readfile()
There are two options for this, you could use the data protocol, which would embed the whole image into the URL of the background ( this isn't recommended if the image is bigger than a few kb. ) or you can use a script to present the image by encoding or recording a unique key for the image, eg bg.php?id=4323-34442-3432-4532 which checks a db for the id to retrieve the file path then echoes the content with the right content type.
Some examples;
based on the Data URI wikipedia page
Data URI Method
Assuming a function like this;
function data_uri($fileID) {
$fRecord = mysql_fetch_array(
mysql_select("SELECT filePath, mimeType from fileTable WHERE fileID = " $fileID . ";")
);
$contents = file_get_contents($fRecord['filePath']);
$base64 = base64_encode($contents);
return "data:$fRecord['mimeType'];base64,$base64";
}
Then in your html/php page you'd have the following snippet
style="background-image:url('<?php echo data_uri($fileID);?>'
PHP Image Dump
Assuming a function like this;
// Given a filename and a mimetype; dump the contents to the screen
function showDocumentContent($fileID){
$fRecord = mysql_fetch_array(
mysql_select("SELECT filePath, mimeType from fileTable WHERE fileID = " $fileID . ";")
);
header( 'Content-Encoding: none', true );
header( 'Content-Type: ' . $fRecord['mimeType'], true );
echo readfile( $fRecord['filePath'] );
}
Then in your html page you'd have this;
style="background-image:url('image.php?fileID=123')
In the first case, images larger than a few KB will result in equally large HTML pages, and may not be supported in browsers consistently. In the second case, you'd effectively have created a php script that is pretending to be an image. In both cases, the real path to the binary files on your server is abstracted away by storing a mapping in a database.
If you store the paths to the files somewhere like a database or a file, you can use readfile() to output the file once you retrieve the path.
Combine that with the content-type header, and set the background-image URL to the PHP script with the correct query string like so:
style="background-image:url('script.php?img=30382');"
You must expose some path to the client, because their browser has to access the file. You can use your webserver config to serve at an indirected location, or serve the image with PHP and have the real path in a call to readfile()

Moving images from doc root for added security

My site uses bookmarklets to gather data from external sites, kinda like Pinterest. I'm concerned about security and want to move the images the bookmarklet gathers from the doc root up one level. My script has some hefty security checks in place, but I want to add this as a last line of defense.
How do I access my images within my script? Obviously using ../userimages/id/image.jpg wont work. I'm using Apache.
Thanks!
Proxy the image
You would use a proxy script to feed the images through like the following example:
// open the file in a binary mode
$name = '../userimages/id/image.jpg';
$fp = fopen($name, 'rb');
// send the right headers
header("Content-Type: image/png");
header("Content-Length: " . filesize($name));
// you may like to set some cache headers here
// dump the picture and stop the script
fpassthru($fp);
exit;
This example is from the PHP manuals fpassthru() page. You would save this script somewhere in your servers document root/httpdocs folder.
"Spoofing" the URL to the image
The easiest way to give the PHP file the appearance of being an image file to a user/browser is to use Apaches mod_rewrite. Usually I use a URL structure something like this:
http://www.example.org/image-id/image.png
Where image-id is the unique identifier for that particular image. This way the file has the correct extensions of an image instead of .php.

Is directly linking to an image okay for images uploaded to the server with a custom PHP script?

For an image file (JPEG) that has been uploaded to the server via a PHP script (to a directory such as http://www.somedomain.com/images, is it a good idea to allow the client to get the image's direct address (such as http://www.somedomain.com/images/someimage.jpg and paste it into a WYWSIWYG text editor (such as TinyMCE)?
I am wondering if there is a preferable method where the direct address is encrypted?
Please, if I should just link directly to the image, just say so.
Thanks!
Note: I have modified this question from my original. Please see revisions if you are curious, but I think I was asking the question incorrectly. My apologies to the people who already answered.
As long as you check correctly WHAT is being uploaded, it shouldn't be a problem. So please at least use getimagesize or a similar function to make sure it's an image that's being uploaded, AND make sure the extension on the file is correct so that it will never be run through the PHP interpreter - to prevent someone from uploading an image with a PHP script attached.
BTW Here's a nice whitepaper on uploads and security : http://www.scanit.be/uploads/php-file-upload.pdf
Depending on the CPU Constraints of your web-hosting service you can write a service to 'serve' the images to your users.
Here is some very BASIC code, it needs spiffing up and cleaning up for XSS/etc...
<?php
$basePath = "/path/to/my/image/store/not/web/accessible/";
$file = NULL;
if (isset($_GET['file']))
$file = $_GET['file'];
if ($file != NULL)
{
$path = $basePath . $file;
// $file needs to be checked for people
// trying to hack you, but for the sake of simplicity
// i've left it out
$mime = mime_content_type($path);
$size = filesize($path);
header("Content-Length: " . $size);
header("Content-Type: " . $mime);
header('Expires: 0');
readfile($path); // Outputs the file to the output buffer
}
?>
Obviously you can put whatever security checks in here you want. But this way your files are below the web dir, and you can apply logic to thier accesibility. This is typically used more for FILE vs. Images, but you can do the same thing here.
Images Accessed like this
http://www.mysite.com/image.php?file=hello.jpg
And you can use mod_rewrite to rewrite urls like this:
`http://www.mysite.com/images/hello.jpg
Into the first url.
I Cannot stress enough the need for further security checking in the above example, it was intended to show you how to serve a file to the user using PHP. Please don't copy & use this verbatim.
Wordpress uses direct links for images. The permalink function simply puts the image on a page along with metadata for comments, but the images' SRC attributes still link directly to the image.
why are you concerned about revealing your image location. Hotlinking?
if so you can prevent hotlinking with htaccess
http://altlab.com/htaccess_tutorial.html
Didn't you get your answer already?
Every site reveals image location to the browser. It's just the way web works.
Got any reason to "encrypt" original location?

Categories