///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This software is based on the PHP3 port of CGI::FastTemplate by Jason Moore jmoore@sober.com
//
// PHP3 port by CDI cdi@thewebmasters.net
//
// gzip compression support added by Knut Bochmann knut@bochmann.de
// performance improvements and ASCIIpack by Andreas Hecht ahecht@bochman.de
//
// This program is free software; you can redistribute it and/or modify it under
// the GNU Library General Public License, with the following stipulations;
// Changes or modifications must retain these Copyright statements. Changes or
// modifications must be submitted to all AUTHORS.
//
// This program is released under the Library General Public License.
//
// 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 Artistic License for more details.
//
// This software is distributed AS-IS.
//
// Last modified: 07/21/2003
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////
// class FastTemplate
///////////////////////
class FastTemplate {
var $FILELIST = array(); // Holds the array of filehandles FILELIST[HANDLE] == "fileName"
var $DYNAMIC = array(); // Holds the array of dynamic blocks, and the fileHandles they live in.
var $PARSEVARS = array(); // Holds the array of Variable handles. PARSEVARS[HANDLE] == "value"
var $LOADED = array(); // We only want to load a template once - when it's used.
// LOADED[FILEHANDLE] == 1 if loaded undefined if not loaded yet.
var $HANDLE = array(); // Holds the handle names assigned by a call to parse()
var $ROOT = ""; // Holds path-to-templates
var $WIN32 = false; // Set to true if this is a WIN32 server
var $ERROR = ""; // Holds the last error message
var $LAST = ""; // Holds the HANDLE to the last template parsed by parse()
var $STRICT = true; // Strict template checking. Unresolved vars in templates will generate a warning when found.
var $FORCE_GZIP = false; // set this to true in cases where the client doesn't send the Accept-Encoding header but accepts gzip anyway
var $GZIP = false; // toggles the GZIP output compression default
var $APACK = false; // toggles the removing of unnecessary spaces, tabs and newlines (ASCIIpack)
var $NO_COMMENTS = false; // removes HTML comments
///////////////
// FastTemplate
///////////////
function FastTemplate ($pathToTemplates = "") {
global $php_errormsg;
if(!empty($pathToTemplates)) $this->set_root($pathToTemplates);
} // end (new) FastTemplate ()
//////////////////////////////////////////////////////////
// set_root
//
// All templates will be loaded from this "root" directory
// Can be changed in mid-process by re-calling with a new
// value.
//////////////////////////////////////////////////////////
function set_root ($root) {
$trailer = substr($root,-1);
if(!$this->WIN32) {
if((ord($trailer)) != 47) $root = "$root". chr(47);
if(is_dir($root)) $this->ROOT = $root;
else {
$this->ROOT = "";
$this->error("Specified ROOT dir [$root] is not a directory");
}
}
else {
if((ord($trailer))!= 92) $root = "$root" . chr(92); // WIN32 box - no testing
$this->ROOT = $root;
}
} // End set_root()
/////////////////////////////////////////////////////////////
// utime
//
// Calculates current microtime
// I throw this into all my classes for benchmarking purposes
// It's not used by anything in this class and can be removed
// if you don't need it.
/////////////////////////////////////////////////////////////
function utime () {
$time = explode( " ", microtime());
$usec = (double)$time[0];
$sec = (double)$time[1];
return $sec + $usec;
} // end utime
//////////////////////////////////////////////////////////////////
// strict
//
// Strict template checking, if true sends warnings to STDOUT when
// parsing a template with undefined variable references
// Used for tracking down bugs-n-such. Use no_strict() to disable.
//////////////////////////////////////////////////////////////////
function strict () {
$this->STRICT = true;
}
/////////////////////////////////////////////////////////////
// Silently discards (removes) undefined variable references
// found in templates
/////////////////////////////////////////////////////////////
function no_strict () {
$this->STRICT = false;
}
////////////////////////////////////////////////////////////////
// is_safe
//
// A quick check of the template file before reading it.
// This is -not- a reliable check, mostly due to inconsistencies
// in the way PHP determines if a file is readable.
////////////////////////////////////////////////////////////////
function is_safe($filename) {
if(!file_exists($filename)) {
$this->error("[$filename] does not exist",0);
return false;
}
return true;
} // is_safe
//////////////////////////////////////////////////
// get_template
//
// Grabs a template from the root dir and
// reads it into a (potentially REALLY) big string
//////////////////////////////////////////////////
function get_template($template) {
if(empty($this->ROOT)) {
$this->error("Cannot open template. Root not valid.",1);
return false;
}
$filename = "$this->ROOT"."$template";
$contents = implode("",(file($filename)));
if((!$contents)or(empty($contents))) {
$this->error("get_template() failure: [$filename] $php_errormsg",1);
}
return $contents;
} // get_template
/////////////////////////////////////////////////////////
// Prints the warnings for unresolved variable references
// in template files. Used if STRICT is true
/////////////////////////////////////////////////////////
function show_unknowns($Line) {
$unknown = array();
if(preg_match("/({[A-Z0-9_]+})/",$Line,$unknown)) {
$UnkVar = $unknown[1];
if(!(empty($UnkVar))) @error_log("[FastTemplate] Warning: no value found for variable: $UnkVar ",0);
}
} // end show_unknowns()
///////////////////////////////////////////////////////////
// parse_template
//
// This routine get's called by parse() and does the actual
// {VAR} to VALUE conversion within the template.
///////////////////////////////////////////////////////////
function parse_template ($template, $tpl_array) {
while(list($key,$val)=each($tpl_array)) {
if(!(empty($key))) {
if(gettype($val) != "string") settype($val,"string");
// php4 doesn't like '{$' combinations.
// $key = '/{'."$key".'}/';
$key = '{'."$key".'}';
// by ahecht@bochmann.de: I've found that str_replace is much faster than preg_replace
// original line was: $template = preg_replace("$key","$val","$template");
$template = str_replace("$key","$val","$template");
}
}
if(!$this->STRICT) $template = preg_replace("/{([A-Z0-9_]+)}/","",$template); // Silently remove anything not already found
else {
if (preg_match("/({[A-Z0-9_]+})/",$template)) { // Warn about unresolved template variables
// by ahecht@bochmann.de: turn off compression for error reporting
$this->set_compression (false);
$unknown = split("\n",$template);
while(list($Element,$Line)=each($unknown)) {
$UnkVar = $Line;
if(!(empty($UnkVar))) $this->show_unknowns($UnkVar);
}
}
}
return $template;
} // parse_template();
///////////////////////////////////////////////////////
// parse
//
// The meat of the whole class. The magic happens here.
///////////////////////////////////////////////////////
function parse( $ReturnVar, $FileTags ) {
$append = false;
$this->LAST = $ReturnVar;
$this->HANDLE[$ReturnVar] = 1;
if (gettype($FileTags) == "array") {
unset($this->$ReturnVar); // Clear any previous data
while(list($key,$val)=each($FileTags)) {
if ((!isset($this->$val)) || (empty($this->$val))) {
$this->LOADED["$val"] = 1;
if(isset($this->DYNAMIC["$val"])) $this->parse_dynamic($val,$ReturnVar);
else {
$fileName = $this->FILELIST["$val"];
$this->$val = $this->get_template($fileName);
}
}
$this->$ReturnVar = $this->parse_template($this->$val,$this->PARSEVARS); // Array context implies overwrite
$this->assign(array($ReturnVar=>$this->$ReturnVar)); // For recursive calls.
}
} // end if FileTags is array()
else { // FileTags is not an array
$val = $FileTags;
if( (substr($val,0,1)) == '.' ) { // Append this template to a previous ReturnVar
$append = true;
$val = substr($val,1);
}
if((!isset($this->$val))||(empty($this->$val))) {
$this->LOADED["$val"] = 1;
if(isset($this->DYNAMIC["$val"])) $this->parse_dynamic($val,$ReturnVar);
else {
$fileName = $this->FILELIST["$val"];
$this->$val = $this->get_template($fileName);
}
}
if ($append) $this->$ReturnVar .= $this->parse_template($this->$val,$this->PARSEVARS);
else $this->$ReturnVar = $this->parse_template($this->$val,$this->PARSEVARS);
$this->assign(array($ReturnVar=>$this->$ReturnVar)); // For recursive calls.
}
return;
} // parse()
////////////
// FastPrint
////////////
function FastPrint($template="") {
if(empty($template)) $template = $this->LAST;
if((!(isset($this->$template)))||(empty($this->$template))) {
$this->error("Nothing parsed, nothing printed",0);
return;
}
else {
if ($this->NO_COMMENTS) {
$this->$template = preg_replace ("//mU","",$this->$template);
}
if ($this->APACK) {
$this->$template = preg_replace ("/[\n\r\s]+/"," ",$this->$template);
}
$this->SetHeader ();
if (($this->CheckCanGzip () || $this->FORCE_GZIP) && $this->GZIP) $this->GzipOut($this->$template);
else print $this->$template;
}
return;
} // end FastPrint
////////
// fetch
////////
function fetch($template="") {
if(empty($template)) $template = $this->LAST;
if((!(isset($this->$template))) || (empty($this->$template))) {
$this->error("Nothing parsed, nothing printed",0);
return "";
}
return($this->$template);
} // end fetch
/////////////////
// define_dynamic
/////////////////
function define_dynamic($Macro, $ParentName) {
// A dynamic block lives inside another template file.
// It will be stripped from the template when parsed
// and replaced with the {$Tag}.
$this->DYNAMIC["$Macro"] = $ParentName;
return true;
} // end define_dynamic
////////////////
// parse_dynamic
////////////////
function parse_dynamic ($Macro,$MacroName) {
// The file must already be in memory.
$ParentTag = $this->DYNAMIC["$Macro"];
if((!$this->$ParentTag) or (empty($this->$ParentTag))) {
$fileName = $this->FILELIST[$ParentTag];
$this->$ParentTag = $this->get_template($fileName);
$this->LOADED[$ParentTag] = 1;
}
if($this->$ParentTag) {
$template = $this->$ParentTag;
$DataArray = split("\n",$template);
$newMacro = "";
$newParent = "";
$outside = true;
$start = false;
$end = false;
while(list($lineNum,$lineData) = each($DataArray)) {
$lineTest = trim($lineData);
if("" == "$lineTest" ) {
$start = true;
$end = false;
$outside = false;
}
if("" == "$lineTest" ) {
$start = false;
$end = true;
$outside = true;
}
if((!$outside) and (!$start) and (!$end)) {
$newMacro .= "$lineData\n"; // Restore linebreaks
}
if(($outside) and (!$start) and (!$end)) {
$newParent .= "$lineData\n"; // Restore linebreaks
}
if($end) {
$newParent .= '{'."$MacroName}\n";
}
// Next line please
if($end) { $end = false; }
if($start) { $start = false; }
} // end While
$this->$Macro = $newMacro;
$this->$ParentTag = $newParent;
return true;
} // $ParentTag NOT loaded - MAJOR oopsie
else {
@error_log("ParentTag: [$ParentTag] not loaded!",0);
$this->error("ParentTag: [$ParentTag] not loaded!",0);
}
return false;
} // parse_dynamic
//////////////////////////////////////////
// clear_dynamic
//
// Strips a DYNAMIC BLOCK from a template.
//////////////////////////////////////////
function clear_dynamic ($Macro="") {
if(empty($Macro)) { return false; }
$ParentTag = $this->DYNAMIC["$Macro"]; // The file must already be in memory.
if((!$this->$ParentTag) or (empty($this->$ParentTag))) {
$fileName = $this->FILELIST[$ParentTag];
$this->$ParentTag = $this->get_template($fileName);
$this->LOADED[$ParentTag] = 1;
}
if($this->$ParentTag) {
$template = $this->$ParentTag;
$DataArray = split("\n",$template);
$newParent = "";
$outside = true;
$start = false;
$end = false;
while(list($lineNum,$lineData)=each($DataArray)) {
$lineTest = trim($lineData);
if("" == "$lineTest" ) {
$start = true;
$end = false;
$outside = false;
}
if("" == "$lineTest" ) {
$start = false;
$end = true;
$outside = true;
}
if(($outside) and (!$start) and (!$end)) {
$newParent .= "$lineData\n"; // Restore linebreaks
}
// Next line please
if($end) { $end = false; }
if($start) { $start = false; }
} // end While
$this->$ParentTag = $newParent;
return true;
} // $ParentTag NOT loaded - MAJOR oopsie
else {
@error_log("ParentTag: [$ParentTag] not loaded!",0);
$this->error("ParentTag: [$ParentTag] not loaded!",0);
}
return false;
} // clear_dynamic
/////////
// define
/////////
function define($fileList) {
while (list($FileTag,$FileName) = each($fileList)) $this->FILELIST["$FileTag"] = $FileName;
return true;
} // define
//////////////
// clear_parse
//////////////
function clear_parse( $ReturnVar = "") {
$this->clear($ReturnVar);
} // clear_parse
////////
// clear
////////
function clear( $ReturnVar = "" ) {
if(!empty($ReturnVar)) { // Clears out hash created by call to parse()
if( (gettype($ReturnVar)) != "array") {
unset($this->$ReturnVar);
return;
}
else {
while(list($key,$val) = each($ReturnVar)) unset($this->$val);
return;
}
}
// Empty - clear all of them
while(list($key,$val) = each($this->HANDLE)) {
$KEY = $key;
unset($this->$KEY);
}
return;
} // end clear()
////////////
// clear_all
////////////
function clear_all() {
$this->clear();
$this->clear_assign();
$this->clear_define();
$this->clear_tpl();
return;
} // end clear_all
/////////////
// clear_tmpl
/////////////
function clear_tpl($fileHandle = "") {
if(empty($this->LOADED)) return true; // Nothing loaded, nothing to clear
if(empty($fileHandle)) {
while(list($key, $val) = each($this->LOADED)) unset($this->$key); // Clear ALL fileHandles
unset($this->LOADED);
return true;
}
else {
if((gettype($fileHandle)) != "array") {
if( (isset($this->$fileHandle)) || (!empty($this->$fileHandle)) )
{
unset($this->LOADED[$fileHandle]);
unset($this->$fileHandle);
return true;
}
}
else {
while(list($Key, $Val) = each($fileHandle)) {
unset($this->LOADED[$Key]);
unset($this->$Key);
}
return true;
}
}
return false;
} // end clear_tpl
///////////////
// clear_define
///////////////
function clear_define( $FileTag = "" ) {
if(empty($FileTag)) {
unset($this->FILELIST);
return;
}
if( (gettype($Files)) != "array") {
unset($this->FILELIST[$FileTag]);
return;
}
else {
while(list($Tag,$Val) = each($FileTag)) unset($this->FILELIST[$Tag]);
return;
}
} // end clear_define
///////////////////////////////////////
// clear_assign
//
// Clears all variables set by assign()
///////////////////////////////////////
function clear_assign() {
if(!(empty($this->PARSEVARS)))
while(list($Ref,$Val) = each($this->PARSEVARS)) unset($this->PARSEVARS["$Ref"]);
} // clear_assign
/////////////
// clera_href
/////////////
function clear_href ($href) {
if(!empty($href)) {
if((gettype($href)) != "array") {
unset($this->PARSEVARS[$href]);
return;
}
else {
while(list($Ref,$val) = each($href)) unset($this->PARSEVARS[$Ref]);
return;
}
}
else $this->clear_assign(); // Empty - clear them all
return;
} // clear_href
/////////
// assign
/////////
function assign($tpl_array, $trailer="") {
if(gettype($tpl_array) == "array") {
while(list($key,$val) = each($tpl_array)) {
if (!(empty($key))) $this->PARSEVARS["$key"] = $val; // Empty values are allowed - Empty Keys are NOT
}
}
else if(!empty($tpl_array)) $this->PARSEVARS["$tpl_array"] = $trailer; // Empty values are allowed in non-array context now.
} // end assign
////////////////////////////////////////////
// get_assigned
//
// Return the value of an assigned variable.
// Christian Brandel cbrandel@gmx.de
////////////////////////////////////////////
function get_assigned($tpl_name = "") {
if(empty($tpl_name)) { return false; }
if(isset($this->PARSEVARS["$tpl_name"])) return ($this->PARSEVARS["$tpl_name"]);
else return false;
} // end get_assigned
////////
// error
////////
function error ($errorMsg, $die = 0) {
$this->ERROR = $errorMsg;
echo "ERROR: $this->ERROR
\n";
if ($die == 1) exit;
return;
} // end error()
/* Functions for toggling ASCII pack */
//////////////////////////////////////////////////////////////////
// set_asciipack (on by default)
//
// turns on ascii pack
//////////////////////////////////////////////////////////////////
function set_asciipack ($b = true) {
$this->APACK = $b;
}
//////////////////////////////////////////////////////////////////
// asciipack_enabled ()
//
// returns the status of ASCII pack
//////////////////////////////////////////////////////////////////
function asciipack_enabled () {
return $this->APACK;
}
/* Functions for sending gzip compressed data to the client */
//////////////////////////////////////////////////////////////////
// set_compression (on by default)
//
// turns on gzip output compression
// this has no effect if the client is capable of this feature!
//////////////////////////////////////////////////////////////////
function set_compression ($b = true) {
$this->GZIP = $b;
}
//////////////////////////////////////////////////////////////////
// compression_enabled ()
//
// returns the status of gzip output compression
//////////////////////////////////////////////////////////////////
function compression_enabled () {
return $this->GZIP;
}
//////////////////////////////////////////////////////////////////
// force_gzip ()
//
// forces gzip compressed output, even if the client doesn't sent
// the Accept-Encoding header
//////////////////////////////////////////////////////////////////
function force_gzip () {
$this->FORCE_GZIP = true;
}
////////////////////////////////////////////////////////////////////
// SetHeader () (for internal use only)
//
// sends a header depending on compression is turned on and possible
////////////////////////////////////////////////////////////////////
function SetHeader () {
if (($this->CheckCanGzip() || $this->FORCE_GZIP) && $this->GZIP)
header("Content-Encoding: gzip");
else
header("Content-type: text/html");
}
////////////////////////////////////////////////////////////////////
// CheckCanGzip ()
//
// checks if the client is capable of handling of compressed data
////////////////////////////////////////////////////////////////////
function CheckCanGzip () {
if (!preg_match ('/((x-gzip)|(gzip))/',$_SERVER["HTTP_ACCEPT_ENCODING"],$match) || connection_aborted()) {
return false;
} else {
return $match[1];
}
/*
if (connection_aborted()) return false;
if (strstr ($_SERVER["HTTP_ACCEPT_ENCODING"], "gzip")) {
if (strstr ($_SERVER["HTTP_ACCEPT_ENCODING"], "x-gzip"))
$ENCODING = "x-gzip";
else
$ENCODING = "gzip";
return $ENCODING;
}
else return false;
*/
}
////////////////////////////////////////////////////////////////////
// GzipOut () (for internal use only)
//
// sends gzip compressed data to the client
////////////////////////////////////////////////////////////////////
function GzipOut ($Contents) {
print (pack ('cccccccc',0x1f,0x8b,0x08,0x00,0x00,0x00,0x00,0x00));
$Size = strlen ($Contents);
$Crc = crc32 ($Contents);
$Contents = gzcompress ($Contents);
$Contents = substr ($Contents, 0, strlen ($Contents) - 4);
print $Contents;
print (pack ('V',$Crc));
print (pack ('V',$Size));
exit;
}
} // End class.FastTemplate.php43
?>