HTACCESS Wrappers with PHP
by: Robert Plank
HTACCESS is a remarkable tool you can use for password protection, error handling (like custom 404 pages), or HTTP redirects. It can also be used to transform whole folders in seconds: adding headers to all your HTML documents, watermarking all your images, and more.
A wrapper is like a middleman. Using htaccess you can tell your web server to กforwardก certain files to PHP scripts of yours. When a visitor tries to load an image in their browser, you could activate a script that adds a watermark to the image. When an HTML page is loaded you could query an IPtocountry database and have your HTML pages translated into the native language of your visitorกs countryoforigin.
Every file in a folder, or all files of a certain type in a folder, can be instructed to go through a PHP script.
Pretend you host several affiliate sites, or a fullblown hosting service like Geocities. Most sites running on free hosting services have some kind of advertisement the owners use to generate revenue. These aren’t applied voluntarily by the users of these services. The ads don’t even show up on their source files, just when displayed on the web.
Itกs possible to replicate this feature using less than 10 lines of PHP and htaccess code. To start off, make a folder on your web host called กheaderก. Create a new text file and enter the following:
AddHandler headered .htm
AddHandler headered .html
Action headered /header/header.php
This designates files with the extension ก.htmก and ก.htmlก to a type called กheaderedก. The name กheaderedก can really be anything, itกs just a way of labeling a group of files. The last line there tells the web server that if any of the file types in the group called กheaderedก are called, we should instead execute the script ก/header/header.phpก. This is the relative path, so if your URL is http://your.host, this will run http://your.host/header/header.php.
Thatกs all youกve got to do for the htaccess file. Save that as กhtaccess.txtก weกll get back to it later.
For the actual wrapper, create a new text file with the standard tags, then assign your header and footer file names to variables called $header and $footer.
$header = กheader.htmlก;
$footer = กfooter.htmlก;
Redirecting a user to our script doesn’t pass its contents to it, just the filename. If you call phpinfo() in your script and scroll to the bottom you can see all the server variables which give us the name. The element ‘reQUEST_URIก in $_SERVER gives us the relative path (/header/sample.html), but we want the full system path since we’re going to be reading the actual file (/home/username/wwwroot/your.host/header/sample.html), which is กPATH_TRANSLATEDก.
$file = $_SERVER[กPATH_TRANSLATEDก];
The name of the file that just tried to be shown is now stored in the variable $file. Three simple things are left: output the header, output the actual file, then output the footer.
Thatกs it. Hereกs the entire header.php file:
All that, in just nine lines of code. Download it here: http://www.jumpx.com/tutorials/wrapper/header.zip
That contains the htaccess file and PHP wrapper script, along with a sample header, footer, and a test page. Upload all five files to your web host, chmod htaccess.txt to 0755 then rename it to ก.htaccessก. It might disappear from your directory listing which is okay, it should still be there.
Load, in your browser, the copy of sample.html residing on your web server. The text ‘this is my headerก should appear at the top while ‘this is my footerก should show on the bottom. If you open up the actual file called sample.html, youกll see that these actually aren’t there. Theyกve been added in by the script all HTML files in the folder กheaderก must now pass through.
This is how wrappers work. Certain things, like adding custom headers and footers are done กon the flyก without modifying your original file. Youกll get the same effect if you create other HTML files and upload them to this folder.
Files without ก.htmlก or ก.htmก extensions, such as text files or images, won’t show these headers or footers. This is a good thing because text files aren’t part of the presentation on a web site and adding extra text to images will corrupt them. It affects all HTML files within your /headers folder, and none of the files outside of it.
If you wanted, you could add or remove any file extensions you want, just by adding or taking away those กAddHandlerก lines.
To get everything back to normal, either delete your .htaccess file or upload a blank .htaccess file in that folder, and all will be well again.
The same basic formula can be applied again for other uses HTTP compression, for example. This was an idea that used to be impractical because computers ran at slower speeds, and is now obsolete because of broadband technologies (DSL and cable).
It works like this: when an HTML page is loaded, the web server instead gives the visitor a zipped or compressed version of that page. The visitor downloads that file, which of course takes up less space than the real thing and downloads in less time, then unzips it and displays the original page.
In this age of lighting fast DSL lines, thereกs almost no noticeable difference. However, if you have a site that hosts large files whose audience is mostly dialup users, it might be something to look into.
Make a new folder called กcompressก. Create your htaccess file again, just as before, but set the extensions to include .htm, .html, and .txt. (The group name, folder name, and script name have nothing to do with one another, you can name any of these whatever you like I just like things to match.)
Our wrapper script for this should be called กcompress.phpก. Thatกs what Iกm naming mine. This means the htaccess file you have should look as follows:
AddHandler compress .html
AddHandler compress .htm
AddHandler compress .txt
Action compress /compress/compress.php
If our wrapper were simply going to pass through the file (in other words, just read its contents into a variable and display it), our handler script would look like this:
กGIFT WRAPPINGก YOUR OUTPUT
To make the HTTP compression work, we use two functions: ob_start() and ob_gzhandler(). Output buffering functions are strange. Any time you try to display something, you can have PHP save up everything you’re trying to output. At the very end itกs all dumped into a function of your choosing where the text can be changed or transformed before itกs output.
There is a builtin PHP function called ob_gzhandler() which takes one parameter (a string of text), compresses the data according to the gzip standard and does all the header trickery thatกs needed to tell the userกs browser that we are transmitting data that needs to be decompressed once itกs downloaded. When this line is used:
It tells PHP: everything displayed afterwards has to go through the function ob_gzhandler() first. Put that at the top of our script and hereกs what weกve got:
Save that as compress.php. Upload both files, chmod htaccess.txt to 0755 and rename to .htaccess and you’re done. Thatกs all you need for it to work, and you can just as easily apply HTTP compression to any script by just adding that line.
To try this puppy out, I got on a dialup connection and put a copy of ‘the Decline And Fall Of The Roman Empire Volume 1ก on my web host, a 900 page book, about 1.6 megabytes in size. Without HTTP compression it took 5 and a half minutes to download. With the compression, only 2 minutes. Internet Explorer told me the download was going at 20 KB per second, impossible with a dialup connection… but since the file was zipped, I really was downloading 20 KB a second (once the data was decompressed on my end) over a 5 KB per second connection.
Though HTTP compression will work on sounds, video, and images, the space you save is negligible, usually only a few bytes. These sorts of media are already heavily compressed so zipping makes almost no difference. This is why weกve told htaccess to only use compression on text and HTML, because itกs with human languages like English where a lot of repetition occurs, which means more information can be compressed.
Not all browsers support HTTP compression, but ob_gzhandler() figures out if a browser can support HTTP compression. If the browser doesn’t, the original file is displayed, no harm done.
You can get a copy of this sample script at: http://www.jumpx.com/tutorials/wrapper/compress.zip
Both of these scripts Iกve created for you will work only on static files, files that actually exist such as images or HTML files. If you tried to apply these wrappers asis to PHP scripts, Perl scripts or even HTML pages that use SSI. If your whole site is run by a single script itกs a better idea to hardcode these things right in, anyway.
THE BEST THING SINCE BUBBLE WRAP
This last demonstration of an htaccess wrapper is something that I think most people with content sites have a use for. On the Internet, people steal stuff. Theft of HTML source code is a nuisance, sure, but the lifting of images is more common. Someone likes a logo on your page, or an ebook cover, or a picture of a physical product you’re selling, and it becomes theirs to use.
A practical way to keep this from happening is to add a watermark to all your images, which is your logo or name on a corner somewhere, forcing anyone who takes your graphic to either unwillingly give you credit, or chop off a part of that picture.
Lucky for us, PHP has a set of functions to handle images, and in version 4.3 and above, itกs included by default. Wrappers come in handy here because you might have an entire site full of images and would rather not spend three weeks watermarking tons of images by hand. Maybe you just don’t want to have to juggle two sets of images, one watermarked and one normal.
Download this script from: http://www.jumpx.com/tutorials/wrapper/watermark.zip
The only files you need to worry about in that zip are htaccess.txt and wrapper.php. Upload them to a folder called กwatermarkก, chmod htaccess.txt to 0755 and rename to ก.htaccessก.
The file wrapper.php remain as is. Iกve put comments in the file regarding most of what it does, so if you’re curious go ahead and take a peek.
What the script does is this: It figures out the original image that was supposed to be called. Then it loads the watermark, which Iกve set in wrapper.php to be กwatermark.pngก which is just a PNG image containing the text ‘tHIS IS WATER MARKEDก. The watermark is placed on top of the original, in the lower right corner, and output in the same format (i.e., JPEG) as the original.
You can tell the difference by looking at these two images:
Iกve included several types of images (GIFs, JPGs, and PNGs) in the zip file for you to test out. Once youกve got everything setup, upload those images and see how they look with the watermark.
This script will work with GIFs, JPEGs, and PNGs. Due to a patent issue (which expires worldwide in July 2004) GIFs can only be read, and not output. To make up for this, any of your GIFs will be output as PNGs, which should still work.
If you think about it, a watermark script like this could also be used for a number of things. For example, if you decide to run an image hosting service like AuctionWatch does for eBay users, you could watermark your siteกs URL to the bottom. Your users get a free service and everyone else sees a possible place to get free image hosting, thereกs some nice viral promotion right there.
You could also adapt the script to check the HTTP referer (in the variable $_SERVER[กHTTP_REFERERก]) to see if the image was called offsite. If it was, the script would put the watermark on there but if you called it from a page on your own site, the image would be shown without one.
About The Author
Robert Plank is the creator of Lightning Track, Redirect Pro, Rotatorblaze, and other useful tools.
Want to pick up more programming skills? Then purchase the ebook กSimple PHPก at http://www.simplephp.com
You may reprint this article in full in your newsletter or web site.
This article was posted on January 25, 2004
by Robert Plank