Hi,
I'm building a simple templating system. The major
requirement of the system is that allow custom dynamic
headers, footers, and toolbars based upon the identity of
the user.
The system so far works like this:
- a user enters the site and logs in. The names
of the user's default
template, header, footer, and toolbar are placed
into a cookie
(via Apache::Session).
- when the user requests a page, my handler
intercepts that request, and
looks at the user's cookie. Based upon the
information in it, it grabs the
appropriate template and components from the
filesystem along with the
requested page, rolls them together, and serves
the result.
A sample template file looks like this:
<html>
<head><title>Standard Template</title></head>
<body bgcolor="#ffffff">
<table width="650" cellspacing="0" cellpadding="0"
border="0">
<tr><td colspan="2" width="650" align="left"><!--
Wrapper:header --><br></td></tr>
<tr>
<td width="150" align="left" valign="top"><!--
Wrapper:toolbar --><br></td>
<td width="500" align="left" valign="top"><!-- Content
--><br></td></tr>
<tr><td colspan="2" width="650" align="left"><!--
Wrapper:footer --><br></td></tr>
</table>
</body></html>
Component files, such as the header, footer and toolbar,
are by convention self-contained html tables, ala
# file components/tool/standard
<table width="100%">
<tr><td align="center"><a href="/wrapped/one.html">Link
One</a><br></td></tr>
<tr><td align="center"><a href="/wrapped/two.html">Link
Two</a><br></td></tr>
<tr><td align="center"><a href="/wrapped/three.html">Link
Three</a><br></td></tr>
<tr><td align="center"><a href="/wrapped/four.html">Link
Four</a><br></td></tr>
<tr><td align="center"><a href="/wrapped/five.html">Link
Five</a><br></td></tr>
<tr><td align="center"><a
href="/wrapped/cgi-bin/test.pl">CGI</a><br></td></tr></table>
I have a working version of this handler, but I think that
there's a better way to do it, specifically the part that
manages the content return part of the request. Static
files are simple enough; I open the file and print it to
STDOUT. Scripts, however, need to be handled
differently. The way I'm doing it now works, but it
strikes me as inefficient.
package My::Wrapper;
use strict;
use Apache::Constants qw(:common DONE);
use Apache::Log ();
sub handler {
my ( $r ) = shift;
my ( $log ) = $r->log;
$log->info("Wrapper: Inside Wrapper.");
my ( $template_directory ) = "/www/html/templates/";
my ( $components_directory ) =
'/www/html/components/';
#
# these next four variables will come from the cookie,
they are
# set manually for now.
#
my ( $template ) = $template_directory.'standard';
my ( $header ) =
$components_directory.'head/'.'standard';
my ( $toolbar ) =
$components_directory.'tool/'.'standard';
my ( $footer ) =
$components_directory.'feet/'.'standard';
$r->send_http_header;
if ( -e $template ) {
open( TEMPLATE, "$template" ) or die "Failed to
open template $template: $!";
while (<TEMPLATE>) {
if ( $_ =~
/(.*)<\!--\sWrapper:(\w+)\s-->(.*)/o ) {
my ( $before ) = $1;
my ( $component ) = $2;
my ( $after ) = $3;
my ( $name );
$name = $header if $component eq 'header';
$name = $toolbar if $component eq
'toolbar';
$name = $footer if $component eq 'footer';
print $before; &print_component($name);
print $after;
} elsif ( $_ =~ /(.*)<\!--\sContent\s-->(.*)/o
) {
my ( $before ) = $1;
my ( $after ) = $2;
my ( $file ) = $r->filename;
print $before;
if ( -e $file ) {
if ( $file =~ /(?:cgi|pl)$/ ) {
$log->info("Wrapper: cgi script
requested.");
do $file;
} else {
$log->info("Wrapper: static file
requested.");
open(CONTENT, "$file" ) or die
"Failed to open content file $file: $!";
while (<CONTENT>) {
print $_;
}
close(CONTENT);
}
}
print $after;
} else {
print $_;
}
}
close( TEMPLATE );
}
$log->info("Wrapper: Exiting Wrapper.");
return DONE;
}
sub print_component {
my ( $component ) = shift;
if ( -e $component ) {
open(IN, "$component" ) or die "Failed to open
component $component: $!";
while (<IN>) {
print $_;
}
close(IN);
return 1;
} else {
print "Failed to open component $component.";
return 0;
}
}
1;
__END__
I have experimented with various ways of handling this,
such as printing a redirect, but this is the only way I
could get it to work. I suspect that there is a better way
to do it. I'd rather not `` the script, because of
efficiency worries and the desire to maintain some process
environment variables used in our authentication systems.
Thanks a bunch,
Todd