Rev 1372 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php////////////////////////////////////////////////////////////////////////////////// //// Copyright (C) 2006 Phorum Development Team //// http://www.phorum.org //// //// This program is free software. You can redistribute it and/or modify //// it under the terms of either the current Phorum License (viewable at //// phorum.org) or the Phorum License that was distributed with this file //// //// 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. //// //// You should have received a copy of the Phorum License //// along with this program. //////////////////////////////////////////////////////////////////////////////////if(!defined("PHORUM")) return;// For keeping track of include dependancies, which// are used to let templates automatically rebuild// in case an included subtemplate has been changed.$include_level = 0;$include_deps = array();function phorum_import_template($tplfile, $outfile){global $include_level, $include_deps;$include_level++;// Remember that we used this template.$include_deps[$tplfile] = $outfile;// In case we're handling 0 byte large files, we set $page// directly. Running fread($fp, 0) gives a PHP warning.if (filesize($tplfile)) {$fp=fopen($tplfile, "r");$page=fread($fp, filesize($tplfile));fclose($fp);} else {$page = '';}preg_match_all("/\{[\!\/A-Za-z].+?\}/s", $page, $matches);settype($oldloopvar, "string");settype($loopvar, "string");settype($olddatavar, "string");settype($datavar, "string");$loopvars = array();foreach($matches[0] as $match){unset($parts);$string=substr($match, 1, -1);$string = trim($string);// pre-parse pointer variablesif(strstr($string, "->")){$string=str_replace("->", "']['", $string);}$parts=explode(" ", $string);switch(strtolower($parts[0])){// Commentcase "!":$repl="<?php // ".implode(" ", $parts)." ?>";break;case "include":$repl = file_get_contents(phorum_get_template($parts[1],1));break;case "include_once":$repl="<?php include_once phorum_get_template('$parts[1]'); ?>";break;case "include_var": // include a file given by a variable$repl="<?php include_once phorum_get_template( \$PHORUM[\"DATA\"]['$parts[1]']); ?>";break;// A define is used to create vars for the engine to use.case "define":$repl="<?php \$PHORUM[\"TMP\"]['$parts[1]']='";array_shift($parts);array_shift($parts);foreach($parts as $part){$repl.=str_replace("'", "\\'", $part)." ";}$repl=trim($repl)."'; ?>";break;// A var is used to create vars for the template.case "var":$repl="<?php \$PHORUM[\"DATA\"]['$parts[1]']='";array_shift($parts);array_shift($parts);foreach($parts as $part){$repl.=str_replace("'", "\\'", $part)." ";}$repl=trim($repl)."'; ?>";break;// Run a Phorum hook. The first parameter is the name of the// hook. Other parameters will be passed on as arguments for// the hook function. On argument will be passed directly to// the hook. Multiple arguments will be passed in an array.case "hook":// Setup hook arguments.$hookargs = array();for($i = 2; !empty($parts[$i]); $i++) {// For supporting the following construct, where the// loopvar is passed to the hook in full:// {LOOP SOMELIST}// {HOOK some_hook SOMELIST}// {/LOOP SOMELIST}if (isset($loopvars[$parts[$i]])) {$hookargs[] = "\$PHORUM['TMP']['".addslashes($parts[$i])."']";} else {$index = phorum_determine_index($loopvars, $parts[$i]);$hookargs[] = "\$PHORUM['$index']['".addslashes($parts[$i])."']";}}// Build the replacement string.$repl = "<?php if(isset(\$PHORUM['hooks']['".addslashes($parts[1])."'])) phorum_hook('".addslashes($parts[1])."'";if (count($hookargs) == 1) {$repl .= "," . $hookargs[0];} elseif (count($hookargs) > 1) {$repl .= ",array(" . implode(",", $hookargs) . ")";}$repl .= ");?>";break;// starts a loopcase "loop":$loopvars[$parts[1]]=true;$index=phorum_determine_index($loopvars, $parts[1]);$repl="<?php \$phorum_loopstack[] = isset(\$PHORUM['TMP']['$parts[1]']) ? \$PHORUM['TMP']['$parts[1]']:NULL; if(isset(\$PHORUM['$index']['$parts[1]']) && is_array(\$PHORUM['$index']['$parts[1]'])) foreach(\$PHORUM['$index']['$parts[1]'] as \$PHORUM['TMP']['$parts[1]']){ ?>";break;// ends a loopcase "/loop":if (!isset($parts[1])) print "<h3>Template warning: Missing argument for /loop statement in file '" . htmlspecialchars($tplfile) . "'</h3>";$repl="<?php } if(isset(\$PHORUM['TMP']) && isset(\$PHORUM['TMP']['$parts[1]'])) unset(\$PHORUM['TMP']['$parts[1]']); \$phorum_loopstackitem=array_pop(\$phorum_loopstack); if (isset(\$phorum_loopstackitem)) \$PHORUM['TMP']['$parts[1]'] = \$phorum_loopstackitem;?>";unset($loopvars[$parts[1]]);break;// if and elseif are the same accept how the line startscase "if":case "elseif":// determine if or elseif$prefix = (strtolower($parts[0])=="if") ? "if" : "} elseif";// are we wanting == or !=if(strtolower($parts[1])=="not"){$operator="!=";$parts[1]=$parts[2];if(isset($parts[3])){$parts[2]=$parts[3];unset($parts[3]);} else {unset($parts[2]);}} else {$operator="==";}$index=phorum_determine_index($loopvars, $parts[1]);// if there is no part 2, check that the value is set and not emptyif(!isset($parts[2])){if($operator=="=="){$repl="<?php $prefix(isset(\$PHORUM['$index']['$parts[1]']) && !empty(\$PHORUM['$index']['$parts[1]'])){ ?>";} else {$repl="<?php $prefix(!isset(\$PHORUM['$index']['$parts[1]']) || empty(\$PHORUM['$index']['$parts[1]'])){ ?>";}// if it is numeric, a constant or a string, simply set it as is} elseif(is_numeric($parts[2]) || defined($parts[2]) || preg_match('!"[^"]*"!', $parts[2])) {$repl="<?php $prefix(isset(\$PHORUM['$index']['$parts[1]']) && \$PHORUM['$index']['$parts[1]']$operator$parts[2]){ ?>";// we must have a template var} else {$index_part2=phorum_determine_index($loopvars, $parts[2]);// this is a really complicated IF we are building.$repl="<?php $prefix(isset(\$PHORUM['$index']['$parts[1]']) && isset(\$PHORUM['$index_part2']['$parts[2]']) && \$PHORUM['$index']['$parts[1]']$operator\$PHORUM['$index_part2']['$parts[2]']) { ?>";}// reset $prefix$prefix="";break;// create an elsecase "else":$repl="<?php } else { ?>";break;// close an ifcase "/if":$repl="<?php } ?>";break;case "assign":if(defined($parts[2]) || is_numeric($parts[2])){$repl="<?php \$PHORUM[\"DATA\"]['$parts[1]']=$parts[2]; ?>";} else {$index=phorum_determine_index($loopvars, $parts[2]);$repl="<?php \$PHORUM[\"DATA\"]['$parts[1]']=\$PHORUM['$index']['$parts[2]']; ?>";}break;// this is just for echoing vars from DATA or TMP if it is a loopvardefault:if(defined($parts[0])){$repl="<?php echo $parts[0]; ?>";} else {$index=phorum_determine_index($loopvars, $parts[0]);$repl="<?php echo \$PHORUM['$index']['$parts[0]']; ?>";}}$page=str_replace($match, $repl, $page);}$include_level--;// Did we finish processing our top level template? Then write out// the compiled template to the cache.//// For storing the compiled template, we use two files. The first one// has some code for checking if one of the dependant files has been// updated and for rebuilding the template if this is the case.// This one loads the second file, which is the template itself.//// This two-stage loading is needed to make sure that syntax// errors in a template file won't break the depancy checking process.// If both were in the same file, the complete file would not be run// at all and the user would have to clean out the template cache to// reload the template once it was fixed. This way user intervention// is never needed.if ($include_level == 0){// Find the template name for the top level template.$pathparts = preg_split('[\\/]', $outfile);$fileparts = explode('-', preg_replace('/^.*\//', '', $pathparts[count($pathparts)-1]));$this_template = addslashes($fileparts[2]);// Determine first and second stage cache filenames.$stage1_file = $outfile;$fileparts[3] = "toplevel_stage2";unset($pathparts[count($pathparts)-1]);$stage2_file = implode('/', $pathparts) . '/' . implode('-', $fileparts);// Create code for automatic rebuilding of rendered templates// in case of changes. This is done by checking if one of the// templates in the dependancy list has been updated. If this// is the case, all dependant rendered subtemplates are deleted.// After that phorum_get_template() is called on the top level// template to rebuild all needed templates.$check_deps ="<?php\n" .'$mymtime = @filemtime("' . addslashes($stage1_file) . '");' . "\n" ."\$update_count = 0;\n" ."\$need_update = (\n";foreach ($include_deps as $tpl => $out) {$qtpl = addslashes($tpl);$check_deps .= " @filemtime(\"$qtpl\") > \$mymtime ||\n";}$check_deps = substr($check_deps, 0, -4); // strip trailing " ||\n"$check_deps .="\n" .");\n" ."if (\$need_update) {\n";foreach ($include_deps as $tpl => $out) {$qout = addslashes($out);$check_deps .= " @unlink(\"$qout\");\n";}$check_deps .=" \$tplfile = phorum_get_template(\"$this_template\");\n" ."}\n" ."include(\"" . addslashes($stage2_file) . "\");\n" ."?>\n";// Reset dependancy list for the next phorum_import_template() call.$include_deps = array();// Write out data to the cache.phorum_write_templatefile($stage1_file, $check_deps);phorum_write_templatefile($stage2_file, $page, true);}else{// Write out subtemplate to the cache.phorum_write_templatefile($outfile, $page);}}function phorum_write_templatefile($filename, $content, $is_toplevel = false){if($fp=fopen($filename, "w")) {fputs($fp, "<?php if(!defined(\"PHORUM\")) return; ?>\n");if ($is_toplevel) {fputs($fp, "<?php \$phorum_loopstack = array() ?>\n");}fputs($fp, $content);if (! fclose($fp)) {die("Error on closing $filename. Is your disk full?");}// Some very unusual thing might happen. On Windows2000 we have seen// that the webserver can write a message to the cache directory,// but that it cannot read it afterwards. Probably due to// specific NTFS file permission settings. So here we have to make// sure that we can open the file that we just wrote.$checkfp = fopen($filename, "r");if (! $checkfp) {die("Failed to write a usable compiled template to $filename. " ."The file was was created successfully, but it could not " ."be read by the webserver afterwards. This is probably " ."caused by the file permissions on your cache directory.");}fclose($checkfp);} else {die("Failed to write a compiled template to $filename. This is " ."probably caused by the file permissions on your cache " ."directory.");}}function phorum_determine_index($loopvars, $varname){if(isset($loopvars) && count($loopvars)){while(strstr($varname, "]")){$varname=substr($varname, 0, strrpos($varname, "]")-1);if(isset($loopvars[$varname])){return "TMP";break;}}}return "DATA";}?>