Templates: Separating Programs from Design
So, how do we turn a hybrid Perl/HTML template into plain HTML to be sent to the user's browser? If users were shown these templates without some sort of translation, they would appear as HTML files with the Perl reproduced verbatim on the user's screen. This display is obviously not desirable.
The key is to have a CGI program, called wrapper.pl, to take the name of a template in its query string (i.e., the argument that a CGI program receives following the question mark in the URL). Once it has received the template name, wrapper.pl creates an instance of Text::Template and instructs that module to perform the magic necessary to turn our template into a page of HTML.We can then send the resulting HTML to our user's browser. As far as the user is concerned, the page was and is HTML; he does not know that we have used a template to create our output.
Here is a simple version of wrapper.pl:
#!/usr/bin/perl - use strict; use diagnostics; use CGI; use Text::Template; # Create an instance of CGI my $query = new CGI; # Send an appropriate MIME header print $query-header("text/html"); # Get the name of the template my $file = "/home/httpd/html/templates/" . $query-param("keywords"); # Create an instance of template my $template = new Text::Template(-type => FILE, -source => $file); # Perform the evaluation, and send the results # to the user's browser print $template-fill_in;
This program may appear quite simple, but we have hidden a great deal of depth within our calls to Text::Template—first when we open the file and when we ask the Template object to evaluate each of the small Perl programs inside the indicated template, it does so. Finally, we take the results of that evaluation and send them to the user's browser with the print statement.
Assuming the directory in which templates are stored not only makes the resulting URLs shorter but also makes your site somewhat more secure, since outsiders will not know your file system. It is also a good idea to remove any references to the parent directory (represented with “..”) in the filename passed to wrapper.pl, so as to avoid turning our program into a convenient way of looking at all of the files on the server's hard disk. One easy way to do this is to replace the original assignment of $file with the following two lines:
# Get the name of the template my $file = "/home/httpd/html/templates/" . $query->param("keywords"); # Remove possible security problems $file =~ s|/\.\./|/|g;
This will remove attempts to ascend one or more directories, making it more difficult for someone to spy on the contents of our server.
Thus, if we have a template named /home/httpd/html/templates/test.tmpl and a site called www.oursite.com, we can view the template in translated form by using the URL http://www.oursite.com/cgi-bin/wrapper.pl?test.tmpl. If we have another template in the same directory named foo.html, we can view it using the URL http://www.oursite.com/cgi-bin/wrapper.pl?foo.html.
One odd note that you should remember when creating templates is the fact that they are effectively served out of the CGI directory on your server (usually called cgi-bin). In all of the above templates, this does not make any difference. If our templates were to incorporate images whose URLs were named relatively (i.e., without a leading slash) rather than absolutely (i.e., with a leading slash), this could cause a problem.
For example, it is quite common for HTML files to be placed in one directory, while the images used by those files are placed in a subdirectory, perhaps named “images”. In order to create an HTML file with an image inside of it, we could do the following:
<HTML> <Head> <Title>Example of image</Title> </Head> <Body> <P>This is a sample Web page, containing an image.</P> <img src="images/graphic.gif"> </Body> </HTML>
But if we were to take this same file and feed it through wrapper.pl, the image would no longer appear. That's because the “image” subdirectory exists relative to the directory in which the HTML file resides, rather than the directory in which the CGI program resides.
One quick solution to this problem is to use the <base> HTML tag, with a URL other than the one under which it was invoked. The <base> tag looks like:
With this tag in place, our browser will know to load the image in the above template from http://www.oursite.com/text/english/images, regardless of whether the document was loaded from within the CGI directory or the original HTML directory. The problem with this approach is that it makes it more difficult to move files and directories to other places on the site—a trade-off that is often worth making.
One word of warning before I conclude. Normally, access to the CGI directory and to the programs contained within it is restricted to a small set of programmers who can be trusted to write and modify code on your system. With templates, that group is suddenly expanded to include all of the site's designers, who could theoretically modify the code within a template to perform malicious acts. Remember that since templates include code, it is a good idea to restrict access to the directory containing the templates, rather than granting it to everyone on your system.
In short, templates are a useful way to separate the design of a web site from the CGI programs it contains. By using them wisely, you will give everyone more freedom to do what they enjoy, as well as what they do best.
Reuven M. Lerner is an Internet and Web consultant living in Haifa, Israel, who has been using the Web since early 1993. In his spare time, he cooks, reads and volunteers with educational projects in his community. You can reach him at email@example.com.
|Designing Electronics with Linux||May 22, 2013|
|Dynamic DNS—an Object Lesson in Problem Solving||May 21, 2013|
|Using Salt Stack and Vagrant for Drupal Development||May 20, 2013|
|Making Linux and Android Get Along (It's Not as Hard as It Sounds)||May 16, 2013|
|Drupal Is a Framework: Why Everyone Needs to Understand This||May 15, 2013|
|Home, My Backup Data Center||May 13, 2013|
- New Products
- Linux Systems Administrator
- Senior Perl Developer
- Technical Support Rep
- UX Designer
- Designing Electronics with Linux
- Dynamic DNS—an Object Lesson in Problem Solving
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- Nice article, thanks for the
8 hours 11 min ago
- I once had a better way I
13 hours 57 min ago
- Not only you I too assumed
14 hours 14 min ago
- another very interesting
16 hours 7 min ago
- Reply to comment | Linux Journal
18 hours 58 sec ago
- Reply to comment | Linux Journal
1 day 55 min ago
- Reply to comment | Linux Journal
1 day 1 hour ago
- Favorite (and easily brute-forced) pw's
1 day 3 hours ago
- Have you tried Boxen? It's a
1 day 8 hours ago
- seo services in india
1 day 13 hours ago
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi
It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?