-1

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:

  1. 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.

  2. 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.

  3. 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?

gogh
  • 73
  • 1
  • 8
  • 1
    Possible duplicate of [Restricting access to images on a website](https://stackoverflow.com/questions/1202335/restricting-access-to-images-on-a-website) – Progman Jun 02 '18 at 23:29
  • It is not a duplicate problem, as I cannot display the html once the headers are sent via readfile(). This results in a headers error "The image cannot be displayed, because it contains errors" – gogh Jun 04 '18 at 12:35

2 Answers2

1

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.

ivanivan
  • 1,999
  • 2
  • 9
  • 9
  • That's what I am trying to do too (point 3), but I want to display the image inline html page. So when I feed back the image through the php class headers are sent I cannot display anything else, while if I display the html page, then the image cannot be displayed due again to the headers being already sent. So (header('Content-type: image/png');) doesn't allow regular html page to be displayed after it, and html page wouldn't allow those headers once started, and skipping those headers will display the image as binary. – gogh Jun 03 '18 at 07:28
  • @gogh - works fine on my system. Editing answer to bring it all together – ivanivan Jun 03 '18 at 13:49
  • Indeed, you are correct, the provided example works and I found my error. inside the inside image tag I was calling php method instead of the php script itself . When I did it like that it worked, the reason was I wanted to use hidden methods but it's not a problem to do this functionality in the public part of the server. – gogh Jun 04 '18 at 13:19
0

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?

gogh
  • 73
  • 1
  • 8