Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks

I was just wondering if there is a way that Perl can display an image located outside the web server directory onto a web site.

Basically the image I want to display is outside the web server directory because I don't want anyone downloading it.

Is there a module or some sort in perl that reads a image and can print it on the web site?

I may be totally off track with the solution I need, any suggestions?

  • Comment on Displaying Image located outside web server dir

Replies are listed 'Best First'.
Re: Displaying Image located outside web server dir
by eibwen (Friar) on May 07, 2005 at 17:08 UTC

    While this will place an additional burden on your webserver, it can be done, so long as perl has permission and access to the image. I think you may be looking for something like:

    #!/usr/bin/perl print <<HEADERS; Content-type: image/png HEADERS print "\n"; open(FILE,'/some/other/path/graphic.png'); binmode FILE; { local $/; print <FILE>; } close FILE;

    If you don't want to encode your own headers and are looking for a slightly simpler solution, check out CGI as well as one of the MIME modules.

    I want to display is outside the web server directory because I don't want anyone downloading it.

    This will prevent anyone from downloading the image directly, but will not prevent anyone from downloading the image through your cgi. The only way to display the image in the first place is for the clients to download the image from the server. While you can change your webserver configuration to preclude external re-displaying of your image, you cannot expect to put it online and have it viewed without having been downloaded.

Re: Displaying Image located outside web server dir
by jhourcle (Prior) on May 07, 2005 at 17:17 UTC

    Here's the basic logic. You'll want to insert whatever extra logic -- but this won't stop anyone from downloading it, as once it's in their browser, they can do anything they want with it. (it can be used to check to see if someone's directly linking to an image, if the browser sends HTTP_REFERER)

    #!/usr/bin/perl -- open (IMAGE, '<', '/path/to/image') or print "500 Server Error\n\n" and exit; print "Content-type: image/gif\n\n", <IMAGE>; close (IMAGE);

    In reality, you want to send the correct MIME type for whatever image you're sending, and send additional headers (cache-control, size of the file, etc.)

    The times that I've done image rotating scripts, I've saved a copy of the image, with full HTTP headers, so I could just dump out the file contents without needing to do any extra parsing to generate headers each time around.

      Hey

      I was just thinking about this topic because I will probably be doing something similar.

      What if you used perl to copy the image to a directory inside your web server directory, then have it displayed through html like normal, then after thats done, have perl delete the image you copied? (sort of like a temp file)

      That way the image can be displayed, but when someone tries to save, it will not find the image since its deleted?

      I'm not sure if this method will work. Anyone have any comments on the flaws with this method?

      perleager

        Once the browser has it, they have it in their cache, and can regenerate it from the cache. It doesn't matter if it's still on the webserver or not.

        As eibwen mentioned -- the file has to be available to the browser for it to be displayed. You have absolutely no control over what the browser can do with an image once they have it. (I've seen sites that use javascript so they can try to keep you from right clicking on an image, but that doesn't help someone linking directly to the image (not through the page you intended), or just turning off javascript.).

        This could turn ugly very quick, with all kinds of race conditions rearing their heads. How do you know when to delete the file? What do you do if the connection gets broken before the whole file is transmitted? You could end up with lots of "old" files sitting around which will need to be reaped after some time. What if several requests come in almost simultaneously? You can't have different files, so all requests will have to "share" the same file and you will need to implement some locking system.

        I don't think it is worth the trouble as anyhow once the file is transmitted to the browser, there is no way you can stop him from saving the file.

        CountZero

        "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Displaying Image located outside web server dir
by TedPride (Priest) on May 07, 2005 at 20:18 UTC
    Any image fed to the web browser can be retrieved and stored. There's no good way to prevent people from getting at single images. However, you can prevent people from downloading your entire image collection, by feeding the images through a script and running some sort of count and/or bot check to prevent mass downloads.
Re: Displaying Image located outside web server dir
by perleager (Pilgrim) on May 07, 2005 at 16:43 UTC
    Hello,

    I'm not really too sure that you can do this.

    Some other solutions you can do is doing some counter measures to protect the image you want to display w/out using some sort of authentication method.

    Such as hotlinking and using a transparent .gif image to cover up the image your displaying--that way they can't right click and save.

    Also if someone views your source to grab the SRC of the image, you may need to do some config on your server to handle images as documents , that way they can't copy the SRC, put it in the browser, then click save as.

    Heres a good article that I read on this topic.

    http://xoops.tedmasterweb.com/modules/articles/print.php?id=5

    Thank you, perleager
Re: Displaying Image located outside web server dir
by stonecolddevin (Parson) on May 07, 2005 at 21:57 UTC
    Is there any reason why you need perl to do this? HTML would work just fine, all you'd have to do is put the URL or absolute path of the file in the IMG src= attribute.
    meh.

      There are actually valid times to do this. (most people would never have a reason to, though).

      In the case in question, the issue was that the files weren't in a directory that the webserver was directly serving. Of course, if that's the only issue, you can just symlink it in to a directory that is being served, or just map the images directory in the webserver.

      Some people use this trick to ensure that someone can't link directly to their images. (eg, you have an image on your website that other people are trying to place in an <img> on their website. Or, any other time that you might have the image vary based on some parameter (randomizing, adjusting by time, or preventing it from being viewed too often is the main reason -- most other things, such as password protection, or varying by accept language, IP range or HTTP_REFERER you can handle through URL rewriting or otherwise through the webserver).

      In some situations, you it might be that the images are actually stored in a database, and not just a file system, so you need to handle the retrieval. In some situations, you might also store the files compressed, and decompress them as they're requested. (this might not be advantageous for most file formats, but you can use this for other types of files, as well.)