serve an image src via a PHP function - php

I have used the construct <img src="http://yoursite.com/image.php?request_id=XXXX">
and it works well to serve images that may need some preprocessing. However, if image.php requires a lot of arguments, the src can become very clumsy. Therefore I thought of wrapping image.php into a function, and bundling it to my content page with include_once "image.php".
The strategy, however, produces the dreaded "Cannot modify header information" error. I believe this is because there is already output on the page, before the img is referenced. Does that mean that it is impossible to output an image src by function rather than by GET a separate file?

This will not work because you are sending two different types of contents in one response, one is text/html and the other for example image/jpeg. Here is my suggestion: have a function that accepts all the arguments you need to render the image and have this function save it somewhere on the disk (cache/images for example) the function should then return the path to this image so you can put it in you src.

Related

Show image based on access privilege

I am trying to display img_a.png or img_b.png based on the access level of the user (e.g. signed in or not). Of course the content (in this case img_a and img_b) should not be available to the general public.
I tried a few solutions, none of them helps me and that's why I look for help here. What I tried so far is:
Based on the user checks I tried adding the resources folder to "open_basedir" which is a lame option but was looking the easiest solution. All ended up by raising a warning that resource is not in the basedir folder through it's obviously there.
Attempted to put the resources in the public folder and restrict them via .htaccess. But in this case they got restricted not only for the unwanted audience but for everyone.
Final and closest attempt was to put back the images outside the webroot and write a class that validates the access and serves the image like:
class Image {
...
public function getImage() {
...
header('Content-Type: '.$this->type);
readfile($this->item);
which afterwards is displayed in the initial script through:
echo "<img src=".$image->getImage($file).">";
The problem above is that the headers were already sent so I could either stream the image or the html output of the .php page but not both. Do I have a way out there?
Create a script that checks whatever user attribute you want, determines what image to serve, and read/send that image. Use the script URL as the <img src=... attribute, ie
<img src='/scripts/user_image.php'>
Something like this will work for PNG images. Similar functions exist for GIF, JPG, etc.
<?php
// do stuff here to determine file name of image to send
if($_SESSION['userlevel']=="ADMIN"){
$imageFilename="admin_image.png";
}
// Create Image From Existing File
$image = imagecreatefrompng($imageFilename);
//Set the Content Type
header('Content-type: image/png');
// Send Image to Browser
imagepng($image);
// Clear Memory
imagedestroy($image);
exit;
?>
OK, per your comment, I think you are referencing things wrong.
My working script is exact as above, only the if-then is commented out. I'm just assigning the filename to the variable. I've named the script user_image.php.
A simple index.html file to reference the image -
<html>
<head><title>test</title></head>
<body>
Hello World!<br />
<img src="user_image.php">
</body>
</html>
And it Just Works. See it in action at https://itsjustcrap.com/img or grab source at https://itsjustcrap.com/img/src.zip
I'll leave it up for a few days, but other than a png image and a commented out if-then, the source is exact same as what is in this post.
Actually I think I found a solution to the headers confict I had.
Displaying the image as data like:
<img src="data:image/png;base64, <?=base64_encode(file_get_contents($file))?>" alt="img">
instead of feeding it inside the source attribute with readfile() php script like:
<img src="image.php?<?=$file?>" alt="my_image">
where the last one was giving me a headers conflict when inside html page.
Discovered the solution over here How to display Base64 images in HTML?

Read multiple image files using php readfile

I am trying to read multiple image files from a folder (.htaccess protected) and display in a HTML page using php readfile().
The problem is I can see only the first image is read and the next is not shown in the browser. The code is as below
<?php
$image1 = 'files/com_download\256\50\www\res\icon\android\icon-36-ldpi.png';
$image2 = 'files/com_download\256\50\www\res\icon\android\icon-48-mdpi.png';
$imginfo = getimagesize($image1);
header("Content-type: ".$imginfo['mime']);
readfile($image1);
$imginfo = getimagesize($image2);
header("Content-type: ".$imginfo['mime']);
readfile($image2);
?>
I could see the first image 'icon-36-ldpi.png' successfully read and displayed in the browser and the second image is not read and not displayed in the browser.
Am I missing something? Any advice please.
Sorry if I am doing stupid but the requirement is to read multiple image files and render in the browser like a grid view. I cannot use img tag because of security reasons.
You can't dump both images out at once. Why not make two images in your html so the browser makes two calls to your script. Then use a GET param to pass the filename you want to display.
---Edit---
Important Security Note
There is an attack vector which you open up when doing soething like this. Someone could easily view your source html and change the parameter to get your image script to output any file they want. They could even use "../../" to go up directories and search for well known files that exist. e.g. "../../../wp_config.php". Now the attacker has your wordpress database credentials. The correct way to prevent against this is to always validate the input parameter properly. For example, only output if the file name ends with ".jpg"

separating image tag from image resizing

I currently have a function in PHP called img(), that takes at least two arguments, as such:
print img("foo.jpg", 100);
That would return something like this:
<img src='/cache/foo_XXXXX.jpg' width='100' height='76' />
So, the function takes the arguments, resize the original file and save it as a cached file on the server and return the image tag. Obviously, if the cached version already exists, it just returns it and saves the processing for the next time.
Now, this works perfectly in 99 cases out of 100, but for some sites there are pages which are quite image-heavy, and since the cached versions of the image is expired after X number of days, the img() functions needs to recreate 50+ high resolution images to small thumbnails, and loading such a page takes several seconds and that's not acceptable.
So my idea is to separate this. So doing this:
print img("foo.jpg", 100);
would return this:
<img src='img.php?ARGUMENTS' width='?' height='?' />
Which means that the img() function doesn't actually handle the file at all, but rather output HTML that tells the browser to get the image from a PHP script rather than a static image file on the server.
Now, the "ARGUMENT" part would of course contain all the information that img.php needs to deal with the file in the same way that img() has dealt with it - perhaps a serialized string version of all the arguments to the function?
But the problem is the width/height values of the image tag! Since processing is moved outside the scope of the current script, it has no idea how large the resulting image would be, right? I obviously can't wait for img.php to complete and return it. I am using imagemagick for the processing (so the second argument can be 100, "50%", "<40" and whatnot) and perhaps there is a way to "dryrun" it with imagemagick - i.e. having imagemagick return the resulting size of a specific file using a specific command?
How would you solve this?
You have the list of all images somewhere in database, right? You can add the fields for width and height and calculate scaled width and height while generating HTML. You could also add thumbnails width and height into database as well.

Inline generated images exceeding length

I am using PHP to generate images and this works fine. I am having trouble displaying these images however:
My image generator is a PHP file that takes tons of parameters and loads of data to generate the image. Because of the excessive amounts that has to be passed to the generator, using the GET container does not work for me, so the data is sent via a POST request. The result of this request is the raw image data.
I am using
$result = post_request('http://myurl.com/graphx/generator.php', $data);
if($result['status'] == 'ok') {
echo "<img src=\"data:image/png;base64,".
base64_encode($result['content'])."\"/>\n";
}
to display my image. This works for very small images, but as they get bigger (300px*300px for example), the image is not displayed anymore (it seems to be cut somewhere).
Is my approach reasonable?
Is there any workaround for the size issue?
Update:
When I let the generator save the image to a file, the created file contains the image as I want it to be. Also, if convert my generator into a GET-generator, the following code works properly as well:
$data = http_build_query($data);
echo "<img src=\"http://myurl.com/graphx/get_generator.php?{$data}\"/>\n";
So it definitely seems to be a problem with either the POST request, or the conversion into the base64 format. I'm using the POST request as shown here.
I'd suggest having your page be structured like this:
main page:
<img src="imageproxy.php" />
imageproxy.php:
<?php
$result = post_request('http://myurl.com/graphx/generator.php', $data);
header('Content-type: image/png');
if($result['status'] == 'ok') {
echo $result['content']);
} else {
readfile('error_message_image.png');
}
instead of trying to work with data uris and length limits, just have your proxy script output the actual raw image data and treat it as an image in your client-side html.
According to http://en.wikipedia.org/wiki/Data_URI_scheme IE 8 (and presumably below if they support it) "limits data URIs to a maximum length of 32 KB". This could be what you are seeing if it only reads the first 32k of whatever you are sending it.
Why don't you base64 the parameters and put THAT in the GET request, and do a simple:
<img src="/path/to/php.php?p=eyJ0aGlzIjoiaXMiLCJhIjoiYmVhdXRpZnVsIiwic2V0Ijoib2YiLCJwYXJhbWV0ZXJzIjoiISEifQ==" />
Then on the php.php base64_decode($p) and return the image.
Even better on php.php, use X-Sendfile mod of apache (https://tn123.org/mod_xsendfile/) and perhaps cache the image as well locally so that you don't have to recreate it all the time
Edit:
I don't know exactly how many parameters we are talking about here. If you go and see What is the maximum length of a URL in different browsers? you will see that experience has shown that a URI is pretty much around 2000 characters.
So it depends if your base64 encoded string is less that that you are safe. Otherwise you could think of alternative ways of encoding. Perhaps yEnc or base85?
Even further you could do store a serialized object (containing the parameters needed) on a local storage (ie RDBMS), link it with an id and pass that id around. When php.php get's the id, looks it up on the storage retrieves the parameters creates the image and so on.

How to load dynamic image w/php gd library, w/o saving it on server or having src="script.php"?

I would like to generate a dynamic image from a script, and then have it load to the browser without being persistent on the server.
However, I cannot call this by setting the image's src="script.php", since that would require running the script that just generated the page and its data all over again, just to get the final data that will generate the graph.
Is there a way to do this that is similar to setting image's src="script.php", but which is called from within another script, and just sends the image without saving it? I need access to the data that is used in the generation of the markup, in order to create this dynamic image.
Or, if not, what is the easiest way to destroy the image once the page is loaded? a quick ajax call?
Is there any way to cache certain data for some limited time frame in order for it to be available to some other script?
Any ideas would be greatly appreciated, as I'm having a really hard time finding the right solution to this...
Thanks!
You can inline the image into a <img> tag if you need to.
Like
<?php
$final_image_data; // Your image data, generated by GD
$base64_data = base64_encode($final_image_data);
echo "<img src=\"data:image/png;base64,{$base64_data}\" ... />";
?>
That should work on all modern browsers, and IE8. Doesn't work well with some email clients tho (Outlook, for one).
Also, another solution I found is to store the image in a session variable which is then called from a php script in the image tag. This would allow a user specific image to be served, and then removed from memory by the script... This also avoids messy img src="" tags...
Hopefully that is helpful to someone.
Use a rewrite rule.
RewriteRule ^magicimage.jpg$ /myscript.php
Then simply echo your image data from gd, instead of writing it to disk -- which is as simple as not providing a filename to the appropriate image*() function
myscript.php
<?php
$im = imagecreatetruecolor($w, $h);
//...do gd stuff...
header('Content-type: image/jpeg');
//this outputs the content directly to the browser
//without creating a temporary file or anything
imagejpeg($im);
And finally, utilize the above
display.php
<img src="magicimage.jpg">

Categories