mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-07 03:44:26 +02:00
- added trusted stream checking to security
- internal changes at file dependency check for caching
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
04/26/2009
|
||||
- added trusted stream checking to security
|
||||
- internal changes at file dependency check for caching
|
||||
|
||||
04/24/2009
|
||||
- changed name of {template} tag to {function}
|
||||
- added new {template} tag
|
||||
|
@@ -47,6 +47,13 @@ define('SMARTY_PARENT_SCOPE', 1);
|
||||
define('SMARTY_ROOT_SCOPE', 2);
|
||||
define('SMARTY_GLOBAL_SCOPE', 3);
|
||||
|
||||
/**
|
||||
* define caching modes
|
||||
*/
|
||||
define('SMARTY_CACHING_OFF', 0);
|
||||
define('SMARTY_CACHING_LIFETIME_CURRENT', 1);
|
||||
define('SMARTY_CACHING_LIVETIME_SAVED', 2);
|
||||
|
||||
/**
|
||||
* load required base class for creation of the smarty object
|
||||
*/
|
||||
@@ -111,7 +118,7 @@ class Smarty extends Smarty_Internal_TemplateBase {
|
||||
// config var settings
|
||||
public $config_overwrite = true; //Controls whether variables with the same name overwrite each other.
|
||||
public $config_booleanize = true; //Controls whether config values of on/true/yes and off/false/no get converted to boolean
|
||||
public $config_read_hidden = true; //Controls whether hidden config sections/vars are read from the file.
|
||||
public $config_read_hidden = true; //Controls whether hidden config sections/vars are read from the file.
|
||||
// config vars
|
||||
public $config_vars = array();
|
||||
// assigned tpl vars
|
||||
@@ -172,9 +179,9 @@ class Smarty extends Smarty_Internal_TemplateBase {
|
||||
* Class constructor, initializes basic smarty properties
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
{
|
||||
// set instance object
|
||||
self::instance($this);
|
||||
self::instance($this);
|
||||
|
||||
if (is_callable('mb_internal_encoding')) {
|
||||
$this->has_mb = true;
|
||||
@@ -204,7 +211,11 @@ class Smarty extends Smarty_Internal_TemplateBase {
|
||||
$this->loadPlugin('Smarty_Internal_Run_Filter');
|
||||
$this->filter_handler = new Smarty_Internal_Run_Filter;
|
||||
if (!$this->debugging && $this->debugging_ctrl == 'URL') {
|
||||
$_query_string = $this->request_use_auto_globals ? isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING']:'' : isset($GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING']) ? $GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING']:'';
|
||||
if (isset($_SERVER['QUERY_STRING'])) {
|
||||
$_query_string = $_SERVER['QUERY_STRING'];
|
||||
} else {
|
||||
$_query_string = '';
|
||||
}
|
||||
if (false !== strpos($_query_string, $this->smarty_debug_id)) {
|
||||
if (false !== strpos($_query_string, $this->smarty_debug_id . '=on')) {
|
||||
// enable debugging for this browser session
|
||||
|
@@ -65,6 +65,15 @@ class Smarty_Security_Policy {
|
||||
* @var array
|
||||
*/
|
||||
public $modifiers = array('escape','count');
|
||||
|
||||
/**
|
||||
* This is an array of trusted streams.
|
||||
*
|
||||
* If empty all streams are allowed.
|
||||
* If set to 'none' none is allowed.
|
||||
* @var array
|
||||
*/
|
||||
public $streams = array('file');
|
||||
/**
|
||||
+ flag if constants can be accessed from template
|
||||
*/
|
||||
|
@@ -44,7 +44,8 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase {
|
||||
$_parent_scope = SMARTY_GLOBAL_SCOPE;
|
||||
}
|
||||
}
|
||||
|
||||
// default for included templates
|
||||
$_caching = SMARTY_CACHING_OFF;
|
||||
/*
|
||||
* if the {include} tag provides individual parameter for caching
|
||||
* it will not be included into the common cache file and treated like
|
||||
@@ -56,21 +57,14 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase {
|
||||
}
|
||||
if (isset($_attr['nocache'])) {
|
||||
if ($_attr['nocache'] == 'true') {
|
||||
$_caching = 'false';
|
||||
$this->compiler->tag_nocache = true;
|
||||
}
|
||||
}
|
||||
if (isset($_attr['caching'])) {
|
||||
if ($_attr['caching'] == 'true') {
|
||||
$_caching = 'true';
|
||||
$_caching = SMARTY_CACHING_LIFETIME_CURRENT;
|
||||
}
|
||||
}
|
||||
|
||||
// if ($this->compiler->tag_nocache == false) {
|
||||
// save file dependency
|
||||
// $compiler->template->properties['file_dependency'][] = array($_template->getTemplateFilepath(), $_template->getTemplateTimestamp());
|
||||
// unset ($_template);
|
||||
// }
|
||||
// create template object
|
||||
$_output = "<?php \$_template = new Smarty_Template ($include_file, \$_smarty_tpl, \$_smarty_tpl->cache_id, \$_smarty_tpl->compile_id);";
|
||||
// delete {include} standard attributes
|
||||
@@ -90,11 +84,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase {
|
||||
if (isset($_caching_lifetime)) {
|
||||
$_output .= "\$_template->caching_lifetime = $_caching_lifetime;";
|
||||
}
|
||||
if (isset($_caching)) {
|
||||
$_output .= "\$_template->caching = $_caching;";
|
||||
} elseif (isset($_caching_lifetime)) {
|
||||
$_output .= "\$_template->caching = true;";
|
||||
}
|
||||
$_output .= "\$_template->caching = $_caching;";
|
||||
// was there an assign attribute
|
||||
if (isset($_assign)) {
|
||||
$_output .= "\$_smarty_tpl->assign($_assign,\$_smarty_tpl->smarty->fetch(\$_template)); ?>";
|
||||
|
@@ -1,20 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Smarty Internal Plugin Compile Internalfunctioncall
|
||||
* Smarty Internal Plugin Compile Internal_Function_Call
|
||||
*
|
||||
* Compiles the {internalfunctioncall} tag
|
||||
* Compiles the {internal_function_call} tag
|
||||
*
|
||||
* @package Smarty
|
||||
* @subpackage Compiler
|
||||
* @author Uwe Tews
|
||||
*/
|
||||
/**
|
||||
* Smarty Internal Plugin Compile Internalfunctioncall Class
|
||||
* Smarty Internal Plugin Compile Internal_Function_Call Class
|
||||
*/
|
||||
class Smarty_Internal_Compile_Internalfunctioncall extends Smarty_Internal_CompileBase {
|
||||
class Smarty_Internal_Compile_Internal_Function_Call extends Smarty_Internal_CompileBase {
|
||||
/**
|
||||
* Compiles code for the {internalfunctioncall} tag
|
||||
* Compiles code for the {internal_function_call} tag
|
||||
*
|
||||
* @param array $args array with attributes from parser
|
||||
* @param object $compiler compiler object
|
||||
@@ -31,8 +31,8 @@ class Smarty_Internal_Compile_Internalfunctioncall extends Smarty_Internal_Compi
|
||||
if (isset($_attr['assign'])) {
|
||||
// output will be stored in a smarty variable instead of beind displayed
|
||||
$_assign = $_attr['assign'];
|
||||
}
|
||||
$_name = trim( $_attr['name'],"'");
|
||||
}
|
||||
$_name = trim($_attr['name'], "'");
|
||||
// create template object
|
||||
$_output = "<?php \$_template = new Smarty_Template ('string:', \$_smarty_tpl);\n";
|
||||
// assign default paramter
|
||||
@@ -51,14 +51,14 @@ class Smarty_Internal_Compile_Internalfunctioncall extends Smarty_Internal_Compi
|
||||
foreach ($_attr as $_key => $_value) {
|
||||
$_output .= "\$_template->assign('$_key',$_value);\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($compiler->template->properties['function'][$_name]['compiled'])) {
|
||||
$_compiled = str_replace(array('_%n',"'"), array("\n","\'"), $compiler->template->properties['function'][$_name]['compiled']);
|
||||
$_compiled = str_replace(array('_%n', "'"), array("\n", "\'"), $compiler->template->properties['function'][$_name]['compiled']);
|
||||
$_output .= "\$_template->compiled_template = '$_compiled';\n \$_template->mustCompile = false;\n";
|
||||
} else {
|
||||
// for recursion
|
||||
// for recursion
|
||||
$_output .= "\$_template->compiled_template = \$_smarty_tpl->compiled_template;\n \$_template->mustCompile = false;\n";
|
||||
}
|
||||
}
|
||||
// was there an assign attribute
|
||||
if (isset($_assign)) {
|
||||
$_output .= "\$_smarty_tpl->assign($_assign,\$_smarty_tpl->smarty->fetch(\$_template)); ?>";
|
@@ -18,8 +18,7 @@ class Smarty_Internal_Debug extends Smarty_Internal_TemplateBase {
|
||||
*/
|
||||
public function display_debug()
|
||||
{
|
||||
$this->smarty = Smarty::instance();
|
||||
|
||||
$this->smarty = Smarty::instance();
|
||||
// get template names
|
||||
$i = 0;
|
||||
$_template_data = array();
|
||||
@@ -32,6 +31,15 @@ class Smarty_Internal_Debug extends Smarty_Internal_TemplateBase {
|
||||
$_template_data[$i]['render_time'] = $_template_obj->render_time;
|
||||
$_template_data[$i]['cache_time'] = $_template_obj->cache_time;
|
||||
$i++;
|
||||
if (false && $i == 1) {
|
||||
foreach ($_template_obj->properties['file_dependency'] as $_file) {
|
||||
$_template_data[$i]['name'] = $_file[0];
|
||||
$_template_data[$i]['compile_time'] = 0;
|
||||
$_template_data[$i]['render_time'] = 0;
|
||||
$_template_data[$i]['cache_time'] = 0;
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,6 @@
|
||||
* This class contains all methods for security checking
|
||||
*/
|
||||
class Smarty_Internal_Security_Handler extends Smarty_Internal_Base {
|
||||
|
||||
/**
|
||||
* Check if PHP function is trusted.
|
||||
*
|
||||
@@ -44,6 +43,22 @@ class Smarty_Internal_Security_Handler extends Smarty_Internal_Base {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Check if stream is trusted.
|
||||
*
|
||||
* @param string $stream_name
|
||||
* @param object $compiler compiler object
|
||||
* @return boolean true if stream is trusted
|
||||
*/
|
||||
function isTrustedStream($stream_name)
|
||||
{
|
||||
if (empty($this->smarty->security_policy->streams) || in_array($stream_name, $this->smarty->security_policy->streams)) {
|
||||
return true;
|
||||
} else {
|
||||
throw new Exception ("stream \"" . $stream_name . "\" not allowed by security setting");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if directory of file resource is trusted.
|
||||
@@ -70,7 +85,7 @@ class Smarty_Internal_Security_Handler extends Smarty_Internal_Base {
|
||||
if ($_cd == $_rp) {
|
||||
return true;
|
||||
} elseif (strncmp($_rp, $_cd, strlen($_cd)) == 0 &&
|
||||
(strlen($_rp) == strlen($_cd) || substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR)) {
|
||||
(strlen($_rp) == strlen($_cd) || substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -90,7 +105,7 @@ class Smarty_Internal_Security_Handler extends Smarty_Internal_Base {
|
||||
function isTrustedPHPDir($filepath)
|
||||
{
|
||||
$_rp = realpath($filepath);
|
||||
if (!empty($this->smarty->security_policy->trusted_dir)) {
|
||||
if (!empty($this->smarty->security_policy->trusted_dir)) {
|
||||
foreach ((array)$this->smarty->security_policy->trusted_dir as $curr_dir) {
|
||||
if (($_cd = realpath($curr_dir)) !== false) {
|
||||
if ($_cd == $_rp) {
|
||||
|
@@ -89,7 +89,8 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
|
||||
$this->caching_type = $this->smarty->default_caching_type;
|
||||
$this->security = $this->smarty->security;
|
||||
$this->cache_resource_class = 'Smarty_Internal_CacheResource_' . ucfirst($this->caching_type);
|
||||
$this->parent = $_parent;
|
||||
$this->parent = $_parent;
|
||||
$this->properties['file_dependency'] = array();
|
||||
// Template resource
|
||||
$this->template_resource = $template_resource;
|
||||
// parse resource name
|
||||
@@ -286,7 +287,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
|
||||
if ($this->compiler_object->compileTemplate($this)) {
|
||||
// compiling succeded
|
||||
if (!$this->isEvaluated()) {
|
||||
// build file dependency string
|
||||
// build template property string
|
||||
$this->properties_string = '<?php /*' . serialize($this->properties) . "*/ ?>\n";
|
||||
// write compiled template
|
||||
$this->smarty->write_file_object->writeFile($this->getCompiledFilepath(), $this->properties_string . $this->dir_acc_sec_string . $this->getCompiledTemplate());
|
||||
@@ -298,7 +299,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
|
||||
throw new Exception("Error compiling template {$this->getTemplateFilepath ()}");
|
||||
return false;
|
||||
}
|
||||
$this->compile_time = $this->_get_time() - $_start_time;
|
||||
$this->compile_time += $this->_get_time() - $_start_time;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,6 +348,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
|
||||
public function writeCachedContent ()
|
||||
{
|
||||
// build file dependency string
|
||||
$this->properties['caching_lifetime'] = $this->caching_lifetime;
|
||||
$this->properties_string = '<?php /*' . serialize($this->properties) . "*/ ?>\n";
|
||||
$this->rendered_content = $this->properties_string . $this->dir_acc_sec_string . $this->rendered_content;
|
||||
return ($this->isEvaluated() || !$this->caching) ? false : $this->cacher_object->writeCachedContent($this);
|
||||
@@ -363,9 +365,29 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
|
||||
{
|
||||
if ($this->isCached === null) {
|
||||
$this->isCached = false;
|
||||
if ($this->caching && !$this->isEvaluated()) {
|
||||
if (!$this->mustCompile() && $this->getTemplateTimestamp() <= $this->getCachedTimestamp() && ((time() <= $this->getCachedTimestamp() + $this->caching_lifetime) || $this->caching_lifetime < 0)) {
|
||||
if ($this->caching && !$this->isEvaluated() && !$this->force_compile) {
|
||||
if ($this->getCachedTimestamp() === false) {
|
||||
return $this->isCached;
|
||||
}
|
||||
if (/*$this->getTemplateTimestamp() <= $this->getCachedTimestamp() && */
|
||||
($this->caching == SMARTY_CACHING_LIVETIME_SAVED || ($this->caching == SMARTY_CACHING_LIFETIME_CURRENT && (time() <= ($this->getCachedTimestamp() + $this->caching_lifetime) || $this->caching_lifetime < 0)))) {
|
||||
$this->rendered_content = $this->cacher_object->getCachedContents($this);
|
||||
$_found = preg_match('~\<\?php /\*(.*)\*/ \?\>~', $this->rendered_content, $_matches);
|
||||
if ($_found) {
|
||||
$this->properties = unserialize($_matches[1]);
|
||||
if ($this->caching == SMARTY_CACHING_LIVETIME_SAVED && (time() > ($this->getCachedTimestamp() + $this->properties['caching_lifetime']) || $this->properties['caching_lifetime'] < 0)) {
|
||||
$this->rendered_content = null;
|
||||
return $this->isCached;
|
||||
}
|
||||
if (!empty($this->properties['file_dependency'])) {
|
||||
foreach ($this->properties['file_dependency'] as $file_to_check) {
|
||||
If (filemtime($file_to_check[0]) > $this->getCachedTimestamp()) {
|
||||
$this->rendered_content = null;
|
||||
return $this->isCached;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->isCached = true;
|
||||
}
|
||||
}
|
||||
@@ -415,10 +437,17 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
|
||||
// include PHP template
|
||||
include($this->getTemplateFilepath ());
|
||||
}
|
||||
$this->render_time = $this->_get_time() - $_start_time;
|
||||
$this->rendered_content = ob_get_clean();
|
||||
$this->render_time += $this->_get_time() - $_start_time;
|
||||
$this->rendered_content = ob_get_clean();
|
||||
if (!$this->isEvaluated) {
|
||||
$this->properties['file_dependency'][] = array($this->getTemplateFilepath(), $this->getTemplateTimestamp());
|
||||
}
|
||||
if ($this->parent instanceof Smarty_Template or $this->parent instanceof Smarty_Internal_Template) {
|
||||
$this->parent->properties['file_dependency'] = array_merge($this->parent->properties['file_dependency'], $this->properties['file_dependency']);
|
||||
}
|
||||
// write to cache when nessecary
|
||||
if (!$this->isEvaluated() && $this->caching) {
|
||||
$this->properties['file_dependency'] = array_unique($this->properties['file_dependency']);
|
||||
// write rendered template
|
||||
$this->writeCachedContent($this);
|
||||
}
|
||||
@@ -452,7 +481,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
|
||||
ob_start();
|
||||
eval("?>" . $this->rendered_content);
|
||||
$this->updateParentVariables();
|
||||
$this->cache_time = $this->_get_time() - $_start_time;
|
||||
$this->cache_time += $this->_get_time() - $_start_time;
|
||||
return (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))?
|
||||
$this->smarty->filter_handler->execute('output', ob_get_clean()) : ob_get_clean();
|
||||
} else {
|
||||
@@ -502,6 +531,9 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
|
||||
$_known_stream = stream_get_wrappers();
|
||||
if (in_array($this->resource_type, $_known_stream)) {
|
||||
// is known stream
|
||||
if ($this->smarty->security) {
|
||||
$this->smarty->security_handler->isTrustedStream($this->resource_type);
|
||||
}
|
||||
if (!isset($this->resource_objects['stream'])) {
|
||||
$this->smarty->loadPlugin('Smarty_Internal_Resource_Stream');
|
||||
$this->resource_objects['stream'] = new Smarty_Internal_Resource_Stream;
|
||||
|
@@ -115,7 +115,7 @@ class Smarty_Internal_TemplateCompilerBase extends Smarty_Internal_Base {
|
||||
if (isset($this->template->properties['function'][$tag])) {
|
||||
// template defined by {template} tag
|
||||
$args['name'] = $tag;
|
||||
$tag = 'internalfunctioncall';
|
||||
$tag = 'internal_function_call';
|
||||
}
|
||||
if (!($_output = $this->$tag($args, $this)) === false) {
|
||||
if ($_output !== true) {
|
||||
|
Reference in New Issue
Block a user