For the Dutchie website I wanted to give my family members a way to upload their pictures but only make them visible to people they want to show them to. The first naive approach to this was to have a folder in my documentroot where the images would be uploaded to. Then there would be a viewer script that would generate <img src=”/folder/…”> HTML code only for those pictures that one’s allowed to see.
This would not stop somebody from manually typing the URL http://dutchie.org/folder/…., so images would still be somewhat visible for outsiders if they could guess the picture names (or if they could just get a directory listing in /folder/).
Ofcourse we could put some authentication check on Apache’s /folder/ but this would then impede the same authentication outside the regular website authentication on the regular users so this option is right out.
Instead I decided to create an upload directory one level above the site’s documentroot. Now the pictures can no longer be accessed directly, with or without an alternative authentication scheme. This also means that I can no longer generate <ims src=”<location of image>” HTML anymore, so clearly we’ll have to think of another way to display those pictures that are outside the document root.
The way I did this is by creating a script showfoto.php in the documentroot of the webserver. I also used a RewriteEngine trick that made any /fotos/show_([\w|\s]+).JPG|GIF|PNG URL be rewritten to showfoto.php?fotourl=$1. The URL will now look like http://dutchie.org/fotos/show_test-picture.JPG, which will be mapped by the rewrite engine to http://dutchie.org/showfoto.php?fotourl=test-picture. The showfoto.php script will check the credentials before sending as it’s very first output:
- header(“Content-type: image/” . $picturetype)
(that’s right, I don’t pass the JPG/GIF/PNG extension through the RewriteEngine; instead the showfoto.php script does a lookup in the database where the URL part is test-picture and when it finds it it also retrieves the picture type, which it concatenates to the image/… header). After sending out that header it’s easy to either generate a new image or to simply output the contents of the file using the picture’s path (which is in the database).