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



Reply via email to