Commit e25e1870 by Seldaek

+ Syntax: Added support for method calls on objects i.e. {$foo->bar()}

+ Added support for smarty security features, see the DwooSecurityPolicy class and $dwoo->setSecurityPolicy() + API: Added a DwooCompiler->setLooseOpeningHandling() method that, if set to true, allows tags to * Fixed {elseif} bug that appeared when multiple elseif tags were used in a row * Syntax: Improved simple math support to work within variable variables (i.e. you can do {$array[$index+1]}) and within strings as well. To prevent this enclose the variables in backticks (i.e. {"$foo/$bar"} will do the math while {"`$foo`/$bar"} won't as $foo is properly delimited) git-svn-id: svn://dwoo.org/dwoo/trunk@4 0598d79b-80c4-4d41-97ba-ac86fbbd088b
parent e31da1c6
[2008--] 0.3.4
+ Syntax: Added support for method calls on objects i.e. {$foo->bar()}
+ Added support for smarty security features, see the DwooSecurityPolicy class
and $dwoo->setSecurityPolicy()
+ API: Added a DwooCompiler->setLooseOpeningHandling() method that, if set to
true, allows tags to
* Fixed {elseif} bug that appeared when multiple elseif tags were used in a row
* Syntax: Improved simple math support to work within variable variables
(i.e. you can do {$array[$index+1]}) and within strings as well. To prevent
this enclose the variables in backticks (i.e. {"$foo/$bar"} will do the math
while {"`$foo`/$bar"} won't as $foo is properly delimited)
[2008-03-19] 0.3.3
+ Syntax: Added support for $dwoo.const.CONSTANT and
$dwoo.const.Class::CONSTANT to read PHP constants from the template
......
......@@ -17,6 +17,10 @@ DwooLoader::loadPlugin('topLevelBlock');
/**
* main dwoo class, allows communication between the compiler, template and data classes
*
* requirements :
* php 5.2.0 or above
* php's mbstring extension for some plugins
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
......@@ -130,6 +134,13 @@ class Dwoo
*/
protected $cacheTime = 0;
/**
* security policy object
*
* @var DwooSecurityPolicy
*/
protected $securityPolicy = null;
/**
* stores the custom plugins callbacks
*
......@@ -159,12 +170,12 @@ class Dwoo
'file' => array
(
'class' => 'DwooTemplateFile',
'compiler' => array('DwooCompiler', 'compilerFactory')
'compiler' => null
),
'string' => array
(
'class' => 'DwooTemplateString',
'compiler' => array('DwooCompiler', 'compilerFactory')
'compiler' => null
)
);
......@@ -306,11 +317,11 @@ class Dwoo
{
$compiler = $this->resources[$tpl->getResourceName()]['compiler'];
if($compiler === null)
if($compiler === null || $compiler === array('DwooCompiler', 'compilerFactory'))
{
if(class_exists('DwooCompiler', false) === false)
include DWOO_PATH . 'DwooCompiler.php';
$compiler = DwooCompiler::getInstance();
$compiler = DwooCompiler::compilerFactory();
}
else
$compiler = call_user_func($compiler);
......@@ -511,9 +522,9 @@ class Dwoo
*
* @param string $name the resource name
* @param string $class the resource class (which must implement DwooITemplate)
* @param callback $compilerFactory the compiler factory callback, a function that must return a compiler instance used to compile this resource, if none is provided
* @param callback $compilerFactory the compiler factory callback, a function that must return a compiler instance used to compile this resource, if none is provided. by default it will produce a DwooCompiler object
*/
public function addResource($name, $class, $compilerFactory = array('DwooCompiler', 'compilerFactory'))
public function addResource($name, $class, $compilerFactory = null)
{
if(strlen($name) < 2)
throw new Exception('Resource names must be at least two-character long to avoid conflicts with Windows paths', E_USER_NOTICE);
......@@ -534,7 +545,7 @@ class Dwoo
{
unset($this->resources[$name]);
if($name==='file')
$this->resources['file'] = array('class'=>'DwooTemplateFile', 'compiler'=>array('DwooCompiler', 'compilerFactory'));
$this->resources['file'] = array('class'=>'DwooTemplateFile', 'compiler'=>null);
}
/* public function addConfig(array $config)
......@@ -700,6 +711,28 @@ class Dwoo
return $this->resources[$resourceName]['compiler'];
}
/**
* sets the security policy object to enforce some php security settings
*
* use this if untrusted persons can modify templates
*
* @param DwooSecurityPolicy $policy the security policy object
*/
public function setSecurityPolicy(DwooSecurityPolicy $policy = null)
{
$this->securityPolicy = $policy;
}
/**
* returns the current security policy object or null by default
*
* @return DwooSecurityPolicy|null the security policy object if any
*/
public function getSecurityPolicy()
{
return $this->securityPolicy;
}
/*
* --------- util functions ---------
*/
......@@ -723,7 +756,8 @@ class Dwoo
*/
public function clearCache($olderThan=0)
{
$cache = new RecursiveDirectoryIterator($this->cacheDir);
$cacheDirs = new RecursiveDirectoryIterator($this->cacheDir);
$cache = new RecursiveIteratorIterator($cacheDirs);
$expired = time() - $olderThan;
$count = 0;
foreach($cache as $file)
......@@ -1485,4 +1519,204 @@ class DwooLoader
}
}
/**
* represents the security settings of a dwoo instance, it can be passed around to different dwoo instances
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* This file is released under the LGPL
* "GNU Lesser General Public License"
* More information can be found here:
* {@link http://www.gnu.org/copyleft/lesser.html}
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @link http://dwoo.org/
* @version 0.3.3
* @date 2008-03-19
* @package Dwoo
*/
class DwooSecurityPolicy
{
/**#@+
* php handling constants, defaults to PHP_REMOVE
*
* PHP_REMOVE : remove all <?php ?> (+ short tags if your short tags option is on) from the input template
* PHP_ALLOW : leave them as they are
* PHP_ENCODE : run htmlentities over them
*
* @var int
*/
const PHP_ENCODE = 1;
const PHP_REMOVE = 2;
const PHP_ALLOW = 3;
/**#@-*/
/**#@+
* constant handling constants, defaults to CONST_DISALLOW
*
* CONST_DISALLOW : throw an error if {$dwoo.const.*} is used in the template
* CONST_ALLOW : allow {$dwoo.const.*} calls
*/
const CONST_DISALLOW = false;
const CONST_ALLOW = true;
/**#@-*/
/**
* php functions that are allowed to be used within the template
*
* @var array
*/
protected $allowedPhpFunctions = array
(
'str_repeat', 'count', 'number_format', 'htmlentities', 'htmlspecialchars',
'long2ip', 'strlen', 'list', 'empty', 'count', 'sizeof', 'in_array', 'is_array',
);
/**
* paths that are safe to use with include or other file-access plugins
*
* @var array
*/
protected $allowedDirectories = array();
/**
* stores the php handling level
*
* defaults to DwooSecurityPolicy::PHP_REMOVE
*
* @var int
*/
protected $phpHandling = self::PHP_REMOVE;
/**
* stores the constant handling level
*
* defaults to DwooSecurityPolicy::CONST_DISALLOW
*
* @var bool
*/
protected $constHandling = self::CONST_DISALLOW;
/**
* adds a php function to the allowed list
*
* @param mixed $func function name or array of function names
*/
public function allowPhpFunction($func)
{
if(is_array($func))
foreach($func as $fname)
$this->allowedPhpFunctions[strtolower($fname)] = true;
else
$this->allowedPhpFunctions[strtolower($func)] = true;
}
/**
* removes a php function from the allowed list
*
* @param mixed $func function name or array of function names
*/
public function disallowPhpFunction($func)
{
if(is_array($func))
foreach($func as $fname)
unset($this->allowedPhpFunctions[strtolower($fname)]);
else
unset($this->allowedPhpFunctions[strtolower($func)]);
}
/**
* returns the list of php functions allowed to run, note that the function names
* are stored in the array keys and not values
*
* @return array
*/
public function getAllowedPhpFunctions()
{
return $this->allowedPhpFunctions;
}
/**
* adds a directory to the safelist for includes and other file-access plugins
*
* @param mixed $path a path name or an array of paths
*/
public function allowDirectory($path)
{
if(is_array($path))
foreach($path as $dir)
$this->allowedDirectories[realpath($dir)] = true;
else
$this->allowedDirectories[realpath($path)] = true;
}
/**
* removes a directory from the safelist
*
* @param mixed $path a path name or an array of paths
*/
public function disallowDirectory($path)
{
if(is_array($path))
foreach($path as $dir)
unset($this->allowedDirectories[realpath($dir)]);
else
unset($this->allowedDirectories[realpath($path)]);
}
/**
* returns the list of safe paths, note that the paths are stored in the array
* keys and not values
*
* @return array
*/
public function getAllowedDirectories()
{
return $this->allowedPHPFunc;
}
/**
* sets the php handling level, defaults to REMOVE
*
* @param int $level one of the DwooSecurityPolicy::PHP_* constants
*/
public function setPhpHandling($level = self::PHP_REMOVE)
{
$this->phpHandling = $level;
}
/**
* returns the php handling level
*
* @return int the current level, one of the DwooSecurityPolicy::PHP_* constants
*/
public function getPhpHandling()
{
return $this->phpHandling;
}
/**
* sets the constant handling level, defaults to CONST_DISALLOW
*
* @param bool $level one of the DwooSecurityPolicy::CONST_* constants
*/
public function setConstantHandling($level = self::CONST_DISALLOW)
{
$this->constHandling = $level;
}
/**
* returns the constant handling level
*
* @return bool the current level, one of the DwooSecurityPolicy::CONST_* constants
*/
public function getConstantHandling()
{
return $this->constHandling;
}
}
?>
\ No newline at end of file
......@@ -88,8 +88,7 @@ interface DwooITemplate
* returns the compiled template file name
*
* @param Dwoo $dwoo the dwoo instance that requests it
* @param DwooICompiler $compiler the compiler that must be used, if null a
* DwooCompiler will be used by default
* @param DwooICompiler $compiler the compiler that must be used
* @return string
*/
public function getCompiledTemplate(Dwoo $dwoo, DwooICompiler $compiler);
......
......@@ -16,7 +16,7 @@ if(class_exists('DwooCompiler', false) === false)
require dirname(__FILE__) . DIRECTORY_SEPARATOR . 'DwooCompiler.php';
/**
* A Smarty compatibility layer for Dwoo
* a Smarty compatibility layer for Dwoo
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
......@@ -36,6 +36,7 @@ if(class_exists('DwooCompiler', false) === false)
*/
class DwooSmarty_Adapter extends Dwoo
{
// magic get/set/call functions that handle unsupported features
public function __set($p, $v)
{
if(array_key_exists($p, $this->compat['properties']) !== false)
......@@ -79,71 +80,76 @@ class DwooSmarty_Adapter extends Dwoo
}
}
// list of unsupported properties and methods
protected $compat = array
(
'methods' => array
(
'register_resource', 'unregister_resource', 'load_filter',
'register_resource', 'unregister_resource', 'load_filter', 'clear_compiled_tpl',
'register_object', 'unregister_object', 'get_registered_object',
'clear_compiled_tpl',
'clear_config', 'get_config_vars', 'config_load'
),
'properties' => array
(
'cache_handler_func' => null,
'debugging' => false,
'error_reporting' => null,
'debugging_ctrl' => 'NONE',
'request_vars_order' => 'EGPCS',
'request_use_auto_globals' => true,
'use_sub_dirs' => false,
'default_resource_type' => 'file',
'cache_handler_func' => null,
'autoload_filters' => array(),
'default_template_handler_func' => '',
'debug_tpl' => '',
'trusted_dir' => array(),
'cache_modified_check' => false,
'secure_dir' => array(),
'security_settings' => array(
'PHP_HANDLING' => false,
'IF_FUNCS' => array('array', 'list',
'isset', 'empty',
'count', 'sizeof',
'in_array', 'is_array',
'true', 'false', 'null'),
'INCLUDE_ANY' => false,
'PHP_TAGS' => false,
'MODIFIER_FUNCS' => array('count'),
'ALLOW_CONSTANTS' => false
),
'default_modifiers' => array(),
'default_resource_type' => 'file',
'config_overwrite' => true,
'config_booleanize' => true,
'config_read_hidden' => false,
'config_fix_newlines' => true,
'config_class' => 'Config_File',
'php_handling' => SMARTY_PHP_PASSTHRU,
'security' => false
),
);
// security vars
public $security = false;
public $trusted_dir = array();
public $secure_dir = array();
public $php_handling = SMARTY_PHP_PASSTHRU;
public $security_settings = array
(
'PHP_HANDLING' => false,
'IF_FUNCS' => array
(
'list', 'empty', 'count', 'sizeof',
'in_array', 'is_array',
),
'INCLUDE_ANY' => false,
'PHP_TAGS' => false,
'MODIFIER_FUNCS' => array(),
'ALLOW_CONSTANTS' => false
);
// paths
public $template_dir = 'templates';
public $compile_dir = 'templates_c';
public $config_dir = 'configs';
public $cache_dir = 'cache';
public $plugins_dir = array();
// misc options
public $left_delimiter = '{';
public $right_delimiter = '}';
public $compile_check = true;
public $force_compile = false;
public $caching = 0;
public $cache_lifetime = 3600;
public $compile_id = null;
public $compile_id = null;
public $compiler_file = null;
public $compiler_class = null;
// dwoo/smarty compat layer
public $show_compat_errors = false;
protected $dataProvider;
protected $_filters = array('pre'=>array(), 'post'=>array(), 'output'=>array());
......@@ -166,6 +172,40 @@ class DwooSmarty_Adapter extends Dwoo
public function fetch($filename, $cacheId=null, $compileId=null, $display=false)
{
if($this->security)
{
$policy = new DwooSecurityPolicy();
$policy->addPhpFunction(array_merge($this->security_settings['IF_FUNCS'], $this->security_settings['MODIFIER_FUNCS']));
$phpTags = $this->security_settings['PHP_HANDLING'] ? SMARTY_PHP_ALLOW : $this->php_handling;
if($this->security_settings['PHP_TAGS'])
$phpTags = SMARTY_PHP_ALLOW;
switch($phpTags)
{
case SMARTY_PHP_ALLOW:
case SMARTY_PHP_PASSTHRU:
$phpTags = DwooSecurityPolicy::PHP_ALLOW;
break;
case SMARTY_PHP_QUOTE:
$phpTags = DwooSecurityPolicy::PHP_ENCODE;
break;
case SMARTY_PHP_REMOVE:
default:
$phpTags = DwooSecurityPolicy::PHP_REMOVE;
break;
}
$policy->setPhpHandling($phpTags);
$policy->setConstantHandling($this->security_settings['ALLOW_CONSTANTS']);
if($this->security_settings['INCLUDE_ANY'])
$policy->allowDirectory(preg_replace('{^((?:[a-z]:)?[\\\\/]).*}i', '$1', __FILE__));
else
$policy->allowDirectory($this->secure_dir);
$this->setSecurityPolicy($policy);
}
if(!empty($this->plugins_dir))
foreach($this->plugins_dir as $dir)
DwooLoader::addDirectory(rtrim($dir, '\\/'));
......@@ -184,7 +224,12 @@ class DwooSmarty_Adapter extends Dwoo
if($this->compiler_file !== null && !class_exists($this->compiler_class, false))
include $this->compiler_file;
$this->compiler = new $this->compiler_class;
}
}
else
{
$this->compiler->addPreProcessor('smarty_compat', true);
$this->compiler->setLooseOpeningHandling(true);
}
$this->compiler->setDelimiters($this->left_delimiter, $this->right_delimiter);
......
......@@ -69,8 +69,7 @@ class DwooTemplateFile extends DwooTemplateString
* returns the compiled template file name
*
* @param Dwoo $dwoo the dwoo instance that requests it
* @param DwooICompiler $compiler the compiler that must be used, if null a
* DwooCompiler will be used by default
* @param DwooICompiler $compiler the compiler that must be used
* @return string
*/
public function getCompiledTemplate(Dwoo $dwoo, DwooICompiler $compiler)
......@@ -94,6 +93,7 @@ class DwooTemplateFile extends DwooTemplateString
$this->compiler = $compiler;
$compiler->setCustomPlugins($dwoo->getCustomPlugins());
$compiler->setSecurityPolicy($dwoo->getSecurityPolicy());
file_put_contents($compiledFile, $compiler->compile(file_get_contents($this->file)));
touch($compiledFile, max($_SERVER['REQUEST_TIME'], filemtime($this->file)));
......@@ -105,7 +105,7 @@ class DwooTemplateFile extends DwooTemplateString
/**
* returns the resource name for this template class
*
*
* @return string
*/
public function getResourceName()
......@@ -122,7 +122,7 @@ class DwooTemplateFile extends DwooTemplateString
{
return $this->file;
}
/**
* returns a new template object from the given include name, null if no include is
* possible (resource not found), or false if include is not permitted by this resource type
......@@ -143,20 +143,25 @@ class DwooTemplateFile extends DwooTemplateString
{
$resourceId = str_replace(array("\t", "\n", "\r"), array('\\t', '\\n', '\\r'), $resourceId);
// TODO check for recursion here if security is enabled
if(file_exists($resourceId))
return new self($resourceId, $cacheTime, $cacheId, $compileId);
if(file_exists($resourceId) === false)
{
$tpl = $dwoo->getCurrentTemplate();
if($tpl instanceof DwooTemplateFile)
{
$resourceId = dirname($tpl->getFilename()).DIRECTORY_SEPARATOR.$resourceId;
if(file_exists($resourceId) === false)
return null;
}
}
$tpl = $dwoo->getCurrentTemplate();
if($tpl instanceof DwooTemplateFile)
if($policy = $dwoo->getSecurityPolicy())
{
$file = dirname($tpl->getFilename()).DIRECTORY_SEPARATOR.$resourceId;
if(file_exists($file))
return new self($file, $cacheTime, $cacheId, $compileId);
$resourceId = realpath($resourceId);
if($resourceId === $this->file)
return $dwoo->triggerError('You can not include a template into itself', E_USER_WARNING);
}
return null;
return new self($resourceId, $cacheTime, $cacheId, $compileId);
}
}
......
......@@ -49,9 +49,9 @@ class DwooTemplateString implements DwooITemplate
/**
* validity duration of the generated cache file (in seconds)
*
*
* set to -1 for infinite cache, 0 to disable and null to inherit the Dwoo instance's cache time
*
*
* @var int
*/
protected $cacheTime;
......@@ -72,10 +72,10 @@ class DwooTemplateString implements DwooITemplate
* @var array
*/
protected static $cache = array('cached'=>array(), 'compiled'=>array());
/**
* holds the compiler that built this template
*
*
* @var DwooICompiler
*/
protected $compiler;
......@@ -135,17 +135,17 @@ class DwooTemplateString implements DwooITemplate
{
return $this->name;
}
/**
* returns the resource name for this template class
*
*
* @return string
*/
public function getResourceName()
{
return 'string';
}
/**
* returns the compiler used by this template, if it was just compiled, or null
*
......@@ -219,11 +219,11 @@ class DwooTemplateString implements DwooITemplate
self::$cache['cached'][$this->cacheId] = true;
}
/**
* clears the cached template if it's older than the given time
*
* @param int $olderThan minimum time (in seconds) required for the cache to be cleared
* @param int $olderThan minimum time (in seconds) required for the cache to be cleared
* @return bool true if the cache was not present or if it was deleted, false if it remains there
*/
public function clearCache($olderThan=0)
......@@ -232,13 +232,12 @@ class DwooTemplateString implements DwooITemplate
return !file_exists($cachedFile) || (filectime($cachedFile) < (time() - $olderThan) && unlink($cachedFile));
}
/**
* returns the compiled template file name
*
* @param Dwoo $dwoo the dwoo instance that requests it
* @param DwooICompiler $compiler the compiler that must be used, if null a
* DwooCompiler will be used by default
* @param DwooICompiler $compiler the compiler that must be used
* @return string
*/
public function getCompiledTemplate(Dwoo $dwoo, DwooICompiler $compiler)
......@@ -262,6 +261,7 @@ class DwooTemplateString implements DwooITemplate
$this->compiler = $compiler;
$compiler->setCustomPlugins($dwoo->getCustomPlugins());
$compiler->setSecurityPolicy($dwoo->getSecurityPolicy());
file_put_contents($compiledFile, $compiler->compile($this->template));
touch($compiledFile, $_SERVER['REQUEST_TIME']);
......
......@@ -35,9 +35,12 @@ class DwooPlugin_elseif extends DwooPlugin_if implements DwooICompilableBlock
$currentBlock =& $compiler->getCurrentBlock();
$currentBlock['params']['postOutput'] = DwooCompiler::PHP_OPEN."\n}".DwooCompiler::PHP_CLOSE;
$out = substr($out, 0, -strlen(DwooCompiler::PHP_CLOSE));
if($out === '')
$out = DwooCompiler::PHP_OPEN."\n}";
else
$out = substr($out, 0, -strlen(DwooCompiler::PHP_CLOSE));
return $out . "elseif(".implode(' ', self::replaceKeywords($params, $compiler)).") {\n" . DwooCompiler::PHP_CLOSE;
return $out . " elseif(".implode(' ', self::replaceKeywords($params, $compiler)).") {\n" . DwooCompiler::PHP_CLOSE;
}
public static function postProcessing(DwooCompiler $compiler, array $params, $prepend='', $append='')
......
......@@ -28,8 +28,6 @@ class DwooPlugin_for extends DwooBlockPlugin implements DwooICompilableBlock
public static function preProcessing(DwooCompiler $compiler, array $params, $prepend='', $append='', $type)
{
// TODO pad the range to 1000 or something if security is enabled
$params = $compiler->getCompiledParams($params);
$tpl = $compiler->getTemplateSource(true);
......
......@@ -48,7 +48,7 @@ class DwooPlugin_smartyinterface extends DwooPlugin
$compiler->curBlock['params']['postOut'] = DwooCompiler::PHP_OPEN.' $_block_content = ob_get_clean(); $_block_repeat=false; echo '.$callback.'$_tag_stack[count($_tag_stack)-1], $_block_content, $this, $_block_repeat); } array_pop($_tag_stack);'.DwooCompiler::PHP_CLOSE;
return DwooCompiler::PHP_OPEN.$prepend.' $_tag_stack[] = '.var_export($params,true).'; $_block_repeat=true; '.$callback.'$_tag_stack[count($_tag_stack)-1], null, $this, $_block_repeat); while ($_block_repeat) { ob_start();'.DwooCompiler::PHP_CLOSE;
return DwooCompiler::PHP_OPEN.$prepend.' if(!isset($_tag_stack)){ $_tag_stack = array(); } $_tag_stack[] = '.var_export($params,true).'; $_block_repeat=true; '.$callback.'$_tag_stack[count($_tag_stack)-1], null, $this, $_block_repeat); while ($_block_repeat) { ob_start();'.DwooCompiler::PHP_CLOSE;
}
public static function postProcessing(DwooCompiler $compiler, array $params, $prepend='', $append='')
......
......@@ -24,7 +24,23 @@ function DwooPlugin_fetch(Dwoo $dwoo, $file, $assign = null)
if($file === '')
return;
// TODO check for security here on http/ftp + secure dirs
if($policy = $dwoo->getSecurityPolicy())
{
while(true)
{
if(preg_match('{^([a-z]+?)://}i', $file))
return $dwoo->triggerError('The security policy prevents you to read files from external sources.', E_USER_WARNING);
$file = realpath($file);
$dirs = $policy->getAllowedDirectories();
foreach($dirs as $dir=>$dummy)
{
if(strpos($file, $dir) === 0)
break 2;
}
return $dwoo->triggerError('The security policy prevents you to read <em>'.$file.'</em>', E_USER_WARNING);
}
}
$file = str_replace(array("\t", "\n", "\r"), array('\\t', '\\n', '\\r'), $file);
$out = file_get_contents($file);
......
......@@ -26,13 +26,35 @@ function DwooPlugin_include(Dwoo $dwoo, $file, $cache_time = null, $cache_id = n
if(preg_match('#^([a-z]{2,}):(.*)#i', $file, $m))
{
$include = $dwoo->getTemplate($m[1], $m[2], $cache_time, $cache_id, $compile_id);
$resource = $m[1];
$identifier = $m[2];
}
else
{
$include = $dwoo->getTemplate('file', $file, $cache_time, $cache_id, $compile_id);
$resource = 'file';
$identifier = $file;
}
if($resource === 'file' && $policy = $dwoo->getSecurityPolicy())
{
while(true)
{
if(preg_match('{^([a-z]+?)://}i', $identifier))
return $dwoo->triggerError('The security policy prevents you to read files from external sources.', E_USER_WARNING);
$identifier = realpath($identifier);
$dirs = $policy->getAllowedDirectories();
foreach($dirs as $dir=>$dummy)
{
if(strpos($identifier, $dir) === 0)
break 2;
}
return $dwoo->triggerError('The security policy prevents you to read <em>'.$identifier.'</em>', E_USER_WARNING);
}
}
$include = $dwoo->getTemplate($resource, $identifier, $cache_time, $cache_id, $compile_id);
if($include === null)
return;
elseif($include === false)
......
......@@ -159,6 +159,13 @@ class BlockTests extends PHPUnit_Framework_TestCase
public function testForeachDwoo()
{
// Item only, key arg is mapped to it just as foreach($foo as $item)
$tpl = new DwooTemplateString('{foreach $sub item}{$item}{/foreach}');
$tpl->forceCompilation();
$this->assertEquals('foobar', $this->dwoo->get($tpl, array('sub'=>array('foo','bar')), $this->compiler));
// Item and key used, key is second just as foreach($foo as $key=>$item)
$tpl = new DwooTemplateString('{foreach $sub key item}{$key}.{$item}{/foreach}');
$tpl->forceCompilation();
......
......@@ -75,7 +75,6 @@ class CoreTests extends PHPUnit_Framework_TestCase
$tpl = new DwooTemplateString('{"foo"|strtoupper}');
$tpl->forceCompilation();
$this->compiler->addPhpFunction('strtoupper');
$this->assertEquals("FOO", $this->dwoo->get($tpl, array(), $this->compiler));
$tpl = new DwooTemplateString('{foreach $foo|count p}{$p}{/foreach}');
......
......@@ -41,10 +41,12 @@ SNIPPET
public function testSmartyCompat()
{
$tpl = new DwooTemplateString('{ldelim}{$smarty.version}{rdelim}');
$tpl = new DwooTemplateString('{ldelim}{$smarty.version}{rdelim}');
$tpl->forceCompilation();
$cmp = new DwooCompiler();
$cmp->addPreProcessor('smarty_compat', true);
$this->assertEquals('{'.Dwoo::VERSION.'}', $this->dwoo->get($tpl, array(), $this->compiler));
$this->assertEquals('{'.Dwoo::VERSION.'}', $this->dwoo->get($tpl, array(), $cmp));
}
}
......
......@@ -279,7 +279,7 @@ class FuncTests extends PHPUnit_Framework_TestCase
$this->assertEquals((string)(3+5+100+20), $this->dwoo->get($tpl, array(), $this->compiler));
$tpl = new DwooTemplateString('{math equation="3+5+$a+b" b="20"}');
$tpl = new DwooTemplateString('{math equation="3+5+`$a`+b" b="20"}');
$tpl->forceCompilation();
$this->assertEquals((string)(3+5+100+20), $this->dwoo->get($tpl, array('a'=>100), $this->compiler));
......
<?php
require_once dirname(dirname(__FILE__)).'/DwooCompiler.php';
function testphpfunc($input) { return $input.'OK'; }
class SecurityTests extends PHPUnit_Framework_TestCase
{
protected $compiler;
protected $dwoo;
protected $policy;
public function __construct()
{
$this->compiler = new DwooCompiler();
$this->dwoo = new Dwoo();
$this->policy = new DwooSecurityPolicy();
$this->dwoo->setSecurityPolicy($this->policy);
}
public function testConstantHandling()
{
$tpl = new DwooTemplateString('{$dwoo.const.DWOO_PATH}');
$tpl->forceCompilation();
$this->assertEquals("", $this->dwoo->get($tpl, array(), $this->compiler));
$this->policy->setConstantHandling(DwooSecurityPolicy::CONST_ALLOW);
$tpl = new DwooTemplateString('{$dwoo.const.DWOO_PATH}');
$tpl->forceCompilation();
$this->assertEquals(DWOO_PATH, $this->dwoo->get($tpl, array(), $this->compiler));
}
public function testPhpHandling()
{
$this->policy->setPhpHandling(DwooSecurityPolicy::PHP_ALLOW);
$tpl = new DwooTemplateString('<?php echo "moo"; ?>');
$tpl->forceCompilation();
$this->assertEquals("moo", $this->dwoo->get($tpl, array(), $this->compiler));
$this->policy->setPhpHandling(DwooSecurityPolicy::PHP_ENCODE);
$tpl = new DwooTemplateString('<?php echo "moo"; ?>');
$tpl->forceCompilation();
$this->assertEquals(htmlspecialchars('<?php echo "moo"; ?>'), $this->dwoo->get($tpl, array(), $this->compiler));
$this->policy->setPhpHandling(DwooSecurityPolicy::PHP_REMOVE);
$tpl = new DwooTemplateString('<?php echo "moo"; ?>');
$tpl->forceCompilation();
$this->assertEquals('', $this->dwoo->get($tpl, array(), $this->compiler));
}
public function testAllowPhpFunction()
{
$this->policy->allowPhpFunction('testphpfunc');
$tpl = new DwooTemplateString('{testphpfunc("foo")}');
$tpl->forceCompilation();
$this->assertEquals("fooOK", $this->dwoo->get($tpl, array(), $this->compiler));
}
}
?>
\ No newline at end of file
{include file="test.tpl" foo=3 bar=4}
\ No newline at end of file
{include file="test.html" foo=3 bar=4}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment