############################################################################# # # NOTE: This file under revision control using RCS # Any changes made without RCS will be lost # # $Source: /usr/local/cvsroot/vbtk/VBTK/PHtml.pm,v $ # $Revision: 1.7 $ # $Date: 2002/03/04 20:53:07 $ # $Author: bhenry $ # $Locker: $ # $State: Exp $ # # Purpose: # # Description: # # Directions: # # Depends on: # # Copyright (C) 1996-2002 Brent Henry # # This program is free software; you can redistribute it and/or # modify it under the terms of version 2 of the GNU General Public # License as published by the Free Software Foundation available at: # http://www.gnu.org/copyleft/gpl.html # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # ############################################################################# # # # REVISION HISTORY: # # $Log: PHtml.pm,v $ # Revision 1.7 2002/03/04 20:53:07 bhenry # *** empty log message *** # # Revision 1.6 2002/03/04 16:49:09 bhenry # Changed requirement back to perl 5.6.0 # # Revision 1.5 2002/03/02 00:53:55 bhenry # Documentation updates # # Revision 1.4 2002/01/23 19:16:48 bhenry # Improved handling of passed parms # # Revision 1.3 2002/01/21 17:07:40 bhenry # Disabled 'uninitialized' warnings # # Revision 1.2 2002/01/18 19:24:50 bhenry # Warning Fixes # # Revision 1.1.1.1 2002/01/17 18:05:57 bhenry # VBTK Project # package VBTK::PHtml; use 5.6.0; use strict; use warnings; # I like using undef as a value so I'm turning off the uninitialized warnings no warnings qw(uninitialized); use VBTK::Common; use FileHandle; our %PHTML_CACHE; our $VERBOSE = $ENV{VERBOSE}; #------------------------------------------------------------------------------- # Function: new # Description: Object constructor. Allocates memory for all class members # Input Parms: # Output Parms: Pointer to class #------------------------------------------------------------------------------- sub new { my $type = shift; my $self = {}; bless $self, $type; my ($fileName,$docRoot) = @_; &log("Setting up new PHtml object for '$fileName'") if ($VERBOSE); $self->{fileName} = $fileName; $self; } #------------------------------------------------------------------------------- # Function: findObj # Description: Check the passed value to see if it's a reference to a PHtml object. # If not, then it must be a filename, so lookup it's object in the # global cache, or create one for it. # Input Parms: # Output Parms: #------------------------------------------------------------------------------- sub findObj { my ($obj) = @_; my $sQuote = '"'; my $dQuote = "'"; # If $obj is not a reference, then it must be a filename if (ref($obj) ne 'PHtml') { # If so, try to look it up in the global cache my $fileName = $obj; &log("Searching for PHtml object for '$fileName'") if ($VERBOSE > 1); # Strip off any double or single quotes $fileName =~ s/[$sQuote$dQuote]//g; # Try to lookup the fileName to see if there's an existing object. $obj = $PHTML_CACHE{$fileName}; # Otherwise, just allocate a new object for it. if (! defined $obj) { $obj = new VBTK::PHtml ($fileName); $PHTML_CACHE{$fileName} = $obj; } } ($obj); } #------------------------------------------------------------------------------- # Function: generateHtml # Description: Read in file, parse out perl, and produce HTML. Note that all # variables in this subroutine start with '_' so as not to conflict # with variables in the parsedContent which are eval'd in the scope # of this subroutine. The base directory must be passed in so that # we know where to find files referenced in '#include' statements # in the phmtl. # Input Parms: Target or object, Base directory of web server # Output Parms: HTML #------------------------------------------------------------------------------- sub generateHtml { my $_obj = shift; my $_baseDir = shift; # These variables will be accessible from within the PHtml my ($_parms,$_conn,$_req) = @_; my ($_html,$evalText); # Just in case a filename was passed, run it through the finder $_obj = &findObj($_obj); &log("Generating PHtml code") if ($VERBOSE > 1); $_obj->parseFile($_baseDir); # Protect local variables from the eval, but pass along a copy of $_baseDir $evalText = "my(\$_baseDir,\$_obj,\$_html,\$evalText);\n\n"; # Make sure the last thing mentioned in the code is the html accumulator, # so that it returns back the html to us. $evalText .= $_obj->{parsedContent} . "\n(\$_html);\n"; # Turn off uninitialized variable warnings temporarily because it's just too # annoying to troubleshoot and it's a very minor thing. # no warnings 'uninitialized'; # Now execute the PHtml, unless we're in debug mode if(! defined $_parms->{debugPHtml}) { &log("Executing PHtml code") if ($VERBOSE > 1); $_html = eval($evalText); } # Turn warnings back on. # use warnings 'uninitialized'; # Dump out the code if we had an error, or if we're in debug mode. if (($@)||(defined $_parms->{debugPHtml})) { my $msg = (! $_parms->{debugPHtml}) ? "Error Parsing PHtml - $@" : "Debug mode specified, dumping code"; &log($msg); my $count = 1; my $code; # Number the lines foreach my $row (split(/\n/,$evalText)) { $code .= sprintf("%04d: %s\n",$count++,$row); } # Convert < and > to html characters. $code =~ s/\<\;/g; $code =~ s/>/\>\;/g; return "
$code"; } &log("Generated PHtml:\n$_html\n") if ($VERBOSE > 3); &log("Generated PHtml") if ($VERBOSE == 3); ($_html); } #------------------------------------------------------------------------------- # Function: parseFile # Description: Read in file and parse out perl and html # Input Parms: # Output Parms: Structure containing perl and html #------------------------------------------------------------------------------- sub parseFile { my $obj = shift; my $baseDir = shift; $obj->loadFile() || return 0; my $fileContent = $obj->{fileContent}; my $directory = $obj->{directory}; my @masterAccum; my $mode='html'; my $LF='"\n"'; my $pound="#"; my ($accum,$modeSwitchFlg,$fileName,$childObj,$rcstag,$includeFileName); # Escape out any RCS tags so they won't be interpreted foreach $rcstag ('source:','revision:','date:') { grep(s/[^\\]\$($rcstag.*)\$/\\\$$1\\\$/i,@{$fileContent}); } # Step through each line from the file foreach (@{$fileContent}) { $modeSwitchFlg = 0; # Watch for #include statements and if found, recurse into the named file if(//) { $includeFileName = $1; # If include filename is relative, then look in the current objects # directory for it. If it's absolute, then build the path from the # base directory. if($includeFileName =~ /^\//) { $includeFileName = $baseDir . $includeFileName; } else { $includeFileName = "$directory/$includeFileName"; } &log("Including file '$includeFileName'") if ($VERBOSE > 2); $childObj=&findObj($includeFileName); $accum .= $`; $accum =~ s/\s+$//; push(@masterAccum, "\$_html .= qq($accum);\n") if ($accum ne ''); $accum = ''; $modeSwitchFlg = 1; if($childObj->parseFile($baseDir)) { push(@masterAccum, "\$_html .= \"\\n\";\n"); push(@masterAccum, $childObj->{parsedContent}); push(@masterAccum, "\$_html .= \"\\n\";\n"); } else { push(@masterAccum, "\$_html .= qq(\n);\n"); } } # If we find a perl marker, then switch to perl mode if(//)) { $accum .= $`; $accum =~ s/