1
0

Smarty bugfix releases, since last upgrade, to 3.1.25

Will now compile vastly better!

Please read change_log.txt and NEW_FEATURES.txt

We may want to use some of these new features in 2.1, which briefly are about:
Namespace support within templates, Security, Compiled Templates, Debugging
This commit is contained in:
Ian
2015-06-16 12:28:49 +02:00
parent 25e374848f
commit b19d6137fb
80 changed files with 8956 additions and 9360 deletions

View File

@ -23,9 +23,9 @@ If $smarty->inheritance_merge_compiled_includes = false; {include} subtemplate w
You must now manually merge all {include} subtemplate which do contain {block} tags. This is done by setting the "inline" option.
{include file='foo.bar' inline}
1. In case of a variable file name like {include file=$foo inline} you must you the variable in a compile_id $smarty->compile_id = $foo;
1. In case of a variable file name like {include file=$foo inline} you must use the variable in a compile_id $smarty->compile_id = $foo;
2. If you use individual compile_id in {include file='foo.tpl' compile_id=$bar inline} it must be used in the
global compile_id as well $smarty->compile_id = $foo;
global compile_id as well $smarty->compile_id = $bar;
3. If call templates with different template_dir configurations and a parent could same named child template from different folders
you must make the folder name part of the compile_id.

View File

@ -0,0 +1,86 @@
This file contains a brief description of new features which have been added to Smarty 3.1
Smarty 3.1.22
Namespace support within templates
==================================
Within templates you can now use namespace specifications on:
- Constants like foo\bar\FOO
- Class names like foo\bar\Baz::FOO, foo\bar\Baz::$foo, foo\bar\Baz::foo()
- PHP function names like foo\bar\baz()
Security
========
- disable special $smarty variable -
The Smarty_Security class has the new property $disabled_special_smarty_vars.
It's an array which can be loaded with the $smarty special variable names like
'template_object', 'template', 'current_dir' and others which will be disabled.
Note: That this security check is performed at compile time.
- limit template nesting -
Property $max_template_nesting of Smarty_Security does set the maximum template nesting level.
The main template is level 1. The nesting level is checked at run time. When the maximum will be exceeded
an Exception will be thrown. The default setting is 0 which does disable this check.
- trusted static methods -
The Smarty_Security class has the new property $trusted_static_methods to restrict access to static methods.
It's an nested array of trusted class and method names.
Format:
array (
'class_1' => array('method_1', 'method_2'), // allowed methods
'class_2' => array(), // all methods of class allowed
)
To disable access for all methods of all classes set $trusted_static_methods = null;
The default value is an empty array() which does enables all methods of all classes, but for backward compatibility
the setting of $static_classes will be checked.
Note: That this security check is performed at compile time.
- trusted static properties -
The Smarty_Security class has the new property $trusted_static_properties to restrict access to static properties.
It's an nested array of trusted class and property names.
Format:
array (
'class_1' => array('prop_1', 'prop_2'), // allowed properties listed
'class_2' => array(), // all properties of class allowed
}
To disable access for all properties of all classes set $trusted_static_properties = null;
The default value is an empty array() which does enables all properties of all classes, but for backward compatibility
the setting of $static_classes will be checked.
Note: That this security check is performed at compile time.
- trusted constants .
The Smarty_Security class has the new property $trusted_constants to restrict access to constants.
It's an array of trusted constant names.
Format:
array (
'SMARTY_DIR' , // allowed constant
}
If the array is empty (default) the usage of constants can be controlled with the
Smarty_Security::$allow_constants property (default true)
Compiled Templates
==================
Smarty does now automatically detects a change of the $merge_compiled_includes and $escape_html
property and creates different compiled templates files depending on the setting.
Same applies to config files and the $config_overwrite, $config_booleanize and
$config_read_hidden properties.
Debugging
=========
The layout of the debug window has been changed for better readability
New class constants
Smarty::DEBUG_OFF
Smarty::DEBUG_ON
Smarty::DEBUG_INDIVIDUAL
have been introduced for setting the $debugging property.
Smarty::DEBUG_INDIVIDUAL will create for each display() and fetch() call an individual gebug window.
.

View File

@ -1,4 +1,4 @@
Smarty 3.1.21
Smarty 3.x
Author: Monte Ohrt <monte at ohrt dot com >
Author: Uwe Tews

View File

@ -0,0 +1,52 @@
#Smarty 3 template engine
##Distribution repository
*Read the NEW_FEATURES file for recent extensions to Smarty 3.1 functionality*
Smarty versions 3.1.11 or later are now on github and can be installed with Composer.
The "smarty/smarty" package will start at libs/.... subfolder.
To get the latest stable version of Smarty 3.1 use
"require": {
"smarty/smarty": "~3.1"
}
in your composer.json file.
To get the trunk version use
"require": {
"smarty/smarty": "~3.1@dev"
}
For a specific version use something like
"require": {
"smarty/smarty": "3.1.19"
}
PHPUnit test can be installed by corresponding composer entries like
"require": {
"smarty/smarty-phpunit": "3.1.19"
}
Similar applies for the lexer/parser generator
"require": {
"smarty/smarty-lexer": "3.1.19"
}
Or you could use
"require": {
"smarty/smarty-dev": "3.1.19"
}
Which is a wrapper to install all 3 packages
Composer can also be used for Smarty2 versions 2.6.24 to 2.6.28

View File

@ -1,8 +1,231 @@
===== 3.1.22-dev ===== (xx.xx.2014)
 ===== 3.1.25===== (15.06.2015)
15.06.2015
- optimization of smarty_cachereource_keyvaluestore.php code
14.06.2015
- bugfix a relative sub template path could fail if template_dir path did contain /../ https://github.com/smarty-php/smarty/issues/50
- optimization rework of path normalization
- bugfix an output tag with variable, modifier followed by an operator like {$foo|modifier+1} did fail https://github.com/smarty-php/smarty/issues/53
13.06.2015
- bugfix a custom cache resource using smarty_cachereource_keyvaluestore.php did fail if php.ini mbstring.func_overload = 2 (forum topic 25568)
11.06.2015
- bugfix the lexer could hang on very large quoted strings (forum topic 25570)
08.06.2015
- bugfix using {$foo} as array index like $bar.{$foo} or in double quoted string like "some {$foo} thing" failed https://github.com/smarty-php/smarty/issues/49
04.06.2015
- bugfix possible error message on unset() while compiling {block} tags https://github.com/smarty-php/smarty/issues/46
01.06.2015
- bugfix <?xml ... ?> including template variables broken since 3.1.22 https://github.com/smarty-php/smarty/issues/47
27.05.2015
- bugfix {include} with variable file name must not create by default individual cache file (since 3.1.22) https://github.com/smarty-php/smarty/issues/43
24.05.2015
- bugfix if condition string 'neq' broken due to a typo https://github.com/smarty-php/smarty/issues/42
===== 3.1.24===== (23.05.2015)
23.05.2015
- improvement on php_handling to allow very large PHP sections, better error handling
- improvement allow extreme large comment sections (forum 25538)
21.05.2015
- bugfix broken PHP 5.2 compatibility when compiling <?php tags https://github.com/smarty-php/smarty/issues/40
- bugfix named {foreach} comparison like $smarty.foreach.foobar.index > 1 did compile into wrong code https://github.com/smarty-php/smarty/issues/41
19.05.2015
- bugfix compiler did overwrite existing variable value when setting the nocache attribute https://github.com/smarty-php/smarty/issues/39
- bugfix output filter trimwhitespace could run into the pcre.backtrack_limit on large output (code.google issue 220)
- bugfix compiler could run into the pcre.backtrack_limit on larger comment or {php} tag sections (forum 25538)
18.05.2015
- improvement introduce shortcuts in lexer/parser rules for most frequent terms for higher
compilation speed
16.05.2015
- bugfix {php}{/php} did work just for single lines https://github.com/smarty-php/smarty/issues/33
- improvement remove not needed ?><?php transitions from compiled code
- improvement reduce number of lexer tokens on operators and if conditions
- improvement higher compilation speed by modified lexer/parser generator at "smarty/smarty-lexer"
13.05.2015
- improvement remove not needed ?><?php transitions from compiled code
- improvement of debugging:
- use fresh Smarty object to display the debug console because of possible problems when the Smarty
was extended or Smarty properties had been modified in the class source
- display Smarty version number
- Truncate lenght of Origin display and extend strin value display to 80 character
- bugfix in Smarty_Security 'nl2br' should be a trusted modifier, not PHP function (code.google issue 223)
12.05.2015
- bugfix {$smarty.constant.TEST} did fail on undefined constant https://github.com/smarty-php/smarty/issues/28
- bugfix access to undefined config variable like {#undef#} did fail https://github.com/smarty-php/smarty/issues/29
- bugfix in nested {foreach} saved item attributes got overwritten https://github.com/smarty-php/smarty/issues/33
===== 3.1.23 ===== (12.05.2015)
12.05.2015
- bugfix of smaller performance issue introduce in 3.1.22 when caching is enabled
- bugfix missig entry for smarty-temmplate-config in autoloader
===== 3.1.22 ===== tag was deleted because 3.1.22 did fail caused by the missing entry for smarty-temmplate-config in autoloader
10.05.2015
- bugfix custom cache resource did not observe compile_id and cache_id when $cache_locking == true
- bugfix cache lock was not handled correctly after timeout when $cache_locking == true
- improvement added constants for $debugging
07.05.2015
- improvement of the debugging console. Read NEW_FEATURES.txt
- optimization of resource class loading
06.05.2015
- bugfix in 3.1.22-dev cache resource must not be loaded for subtemplates
- bugfix/improvement in 3.1.22-dev cache locking did not work as expected
05.05.2015
- optimization on cache update when main template is modified
- optimization move <?php ?> handling from parser to new compiler module
05.05.2015
- bugfix code could be messed up when {tags} are used in multiple attributes https://github.com/smarty-php/smarty/issues/23
04.05.2015
- bugfix Smarty_Resource::parseResourceName incompatible with Google AppEngine (https://github.com/smarty-php/smarty/issues/22)
- improvement use is_file() checks to avoid errors suppressed by @ which could still cause problems (https://github.com/smarty-php/smarty/issues/24)
28.04.2015
- bugfix plugins of merged subtemplates not loaded in 3.1.22-dev (forum topic 25508) 2nd fix
28.04.2015
- bugfix plugins of merged subtemplates not loaded in 3.1.22-dev (forum topic 25508)
23.04.2015
- bugfix a nocache template variable used as parameter at {insert} was by mistake cached
20.04.2015
- bugfix at a template function containing nocache code a parmeter could overwrite a template variable of same name
27.03.2015
- bugfix Smarty_Security->allow_constants=false; did also disable true, false and null (change of 16.03.2015)
- improvement added a whitelist for trusted constants to security Smarty_Security::$trusted_constants (forum topic 25471)
20.03.2015
- bugfix make sure that function properties get saved only in compiled files containing the fuction definition {forum topic 25452}
- bugfix correct update of global variable values on exit of template functions. (reported under Smarty Developers)
16.03.2015
- bugfix problems with {function}{/function} and {call} tags in different subtemplate cache files {forum topic 25452}
- bugfix Smarty_Security->allow_constants=false; did not disallow direct usage of defined constants like {SMARTY_DIR} {forum topic 25457}
- bugfix {block}{/block} tags did not work inside double quoted strings https://github.com/smarty-php/smarty/issues/18
15.03.2015
- bugfix $smarty->compile_check must be restored before rendering of a just updated cache file {forum 25452}
14.03.2015
- bugfix {nocache} {/nocache} tags corrupted code when used within a nocache section caused by a nocache template variable.
- bugfix template functions defined with {function} in an included subtemplate could not be called in nocache
mode with {call... nocache} if the subtemplate had it's own cache file {forum 25452}
10.03.2015
- bugfix {include ... nocache} whith variable file or compile_id attribute was not executed in nocache mode.
12.02.2015
- bugfix multiple Smarty::fetch() of same template when $smarty->merge_compiled_includes = true; could cause function already defined error
11.02.2015
- bugfix recursive {includes} did create E_NOTICE message when $smarty->merge_compiled_includes = true; (github issue #16)
22.01.2015
- new feature security can now control access to static methods and properties
see also NEW_FEATURES.txt
21.01.2015
- bugfix clearCompiledTemplates(), clearAll() and clear() could try to delete whole drive at wrong path permissions because realpath() fail (forum 25397)
- bugfix 'self::' and 'parent::' was interpreted in template syntax as static class
04.01.2015
- push last weeks changes to github
- different optimizations
- improvement automatically create different versions of compiled templates and config files depending
on property settings.
- optimization restructure template processing by moving code into classes it better belongs to
- optimization restructure config file processing
31.12.2014
- bugfix use function_exists('mb_get_info') for setting Smarty::$_MBSTRING.
Function mb_split could be overloaded depending on php.ini mbstring.func_overload
29.12.2014
- new feature security can now limit the template nesting level by property $max_template_nesting
see also NEW_FEATURES.txt (forum 25370)
29.12.2014
- new feature security can now disable special $smarty variables listed in property $disabled_special_smarty_vars
see also NEW_FEATURES.txt (forum 25370)
27.12.2014
- bugfix clear internal _is_file_cache when plugins_dir was modified
13.12.2014
- improvement optimization of lexer and parser resulting in a up to 30% higher compiling speed
11.12.2014
- bugfix resolve parser ambiguity between constant print tag {CONST} and other smarty tags after change of 09.12.2014
09.12.2014
- bugfix variables $null, $true and $false did not work after the change of 12.11.2014 (forum 25342)
- bugfix call of template function by a variable name did not work after latest changes (forum 25342)
23.11.2014
- bugfix a plugin with attached modifier could fail if the tag was immediately followed by another Smarty tag (since 3.1.21) (forum 25326)
13.11.2014
- improvement move autoload code into Autoloader.php. Use Composer autoloader when possible
12.11.2014
- new feature added support of namespaces to template code
08.11.2014 - 10.11.2014
- bugfix subtemplate called in nocache mode could be called with wrong compile_id when it did change on one of the calling templates
- improvement add code of template functions called in nocache mode dynamically to cache file (related to bugfix of 01.11.2014)
- bugfix Debug Console did not include all data from merged compiled subtemplates
04.11.2014
- new feature $smarty->debug = true; => overwrite existing Debug Console window (old behaviour)
$smarty->debug = 2; => individual Debug Console window by template name
03.11.2014
- bugfix Debug Console did not show included subtemplates since 3.1.17 (forum 25301)
- bugfix Modifier debug_print_var did not limit recursion or prevent recursive object display at Debug Console
(ATTENTION: parameter order has changed to be able to specify maximum recursion)
- bugfix Debug consol did not include subtemplate information with $smarty->merge_compiled_includes = true
- improvement The template variables are no longer displayed as objects on the Debug Console
- improvement $smarty->createData($parent = null, $name = null) new optional name parameter for display at Debug Console
- addition of some hooks for future extension of Debug Console
01.11.2014
- bugfix and enhancement on subtemplate {include} and template {function} tags.
* Calling a template which has a nocache section could fail if it was called from a cached and a not cached subtemplate.
* Calling the same subtemplate cached and not cached with the $smarty->merge_compiled_includes enabled could cause problems
* Many smaller related changes
30.10.2014
- bugfix access to class constant by object like {$object::CONST} or variable class name {$class::CONST} did not work (forum 25301)
26.10.2014
- bugfix E_NOTICE message was created during compilation when ASP tags '<%' or '%>' are in template source text
- bugfix merge_compiled_includes option failed when caching enables and same subtemplate was included cached and not cached
===== 3.1.21 ===== (18.10.2014)
18.10.2014
- composer moved to github
- add COMPOSER_RELEASE_NOTES
- composer moved to github
17.10.2014
- bugfix on $php_handling security and optimization of smarty_internal_parsetree (Thue Kristensen)
@ -43,7 +266,7 @@
04.07.2014
- bugfix the bufix of 02.06.2014 broke correct handling of child templates with same name but different template folders in extends resource (issue 194 and topic 25099)
===== 3.1.19 ===== (06.30.2014)
===== 3.1.19 ===== (30.06.2014)
20.06.2014
- bugfix template variables could not be passed as parameter in {include} when the include was in a {nocache} section (topic 25131)
@ -732,7 +955,7 @@
15/07/2011
- bugfix individual cache_lifetime of {include} did not work correctly inside {block} tags
- added caches for Smarty_Template_Source and Smarty_Template_Compiled to reduce I/O for multiple cache_id rendering
- added caches for Smarty_Internal_TemplateSource and Smarty_Internal_TemplateCompiled to reduce I/O for multiple cache_id rendering
14/07/2011
- made Smarty::loadPlugin() respect the include_path if required

View File

@ -0,0 +1,158 @@
<?php
/**
* Smarty Autoloader
*
* @package Smarty
*/
/**
* Smarty Autoloader
*
* @package Smarty
* @author Uwe Tews
* Usage:
* require_once '...path/Autoloader.php';
* Smarty_Autoloader::register();
* $smarty = new Smarty();
* Note: This autoloader is not needed if you use Composer.
* Composer will automatically add the classes of the Smarty package to it common autoloader.
*/
class Smarty_Autoloader
{
/**
* Filepath to Smarty root
*
* @var string
*/
public static $SMARTY_DIR = '';
/**
* Filepath to Smarty internal plugins
*
* @var string
*/
public static $SMARTY_SYSPLUGINS_DIR = '';
/**
* Array of not existing classes to avoid is_file calls for already tested classes
*
* @var array
*/
public static $unknown = array();
/**
* Array with Smarty core classes and their filename
*
* @var array
*/
public static $rootClasses = array('Smarty' => 'Smarty.class.php',
'SmartyBC' => 'SmartyBC.class.php',
);
private static $syspluginsClasses = array(
'smarty_config_source' => true,
'smarty_security' => true,
'smarty_cacheresource' => true,
'smarty_compiledresource' => true,
'smarty_cacheresource_custom' => true,
'smarty_cacheresource_keyvaluestore' => true,
'smarty_resource' => true,
'smarty_resource_custom' => true,
'smarty_resource_uncompiled' => true,
'smarty_resource_recompiled' => true,
'smarty_template_source' => true,
'smarty_template_compiled' => true,
'smarty_template_cached' => true,
'smarty_template_config' => true,
'smarty_data' => true,
'smarty_variable' => true,
'smarty_undefined_variable' => true,
'smartyexception' => true,
'smartycompilerexception' => true,
'smarty_internal_data' => true,
'smarty_internal_template' => true,
'smarty_internal_templatebase' => true,
'smarty_internal_resource_file' => true,
'smarty_internal_resource_extends' => true,
'smarty_internal_resource_eval' => true,
'smarty_internal_resource_string' => true,
'smarty_internal_resource_registered' => true,
'smarty_internal_extension_codeframe' => true,
'smarty_internal_extension_config' => true,
'smarty_internal_filter_handler' => true,
'smarty_internal_function_call_handler' => true,
'smarty_internal_cacheresource_file' => true,
'smarty_internal_write_file' => true,
);
/**
* Registers Smarty_Autoloader backward compatible to older installations.
*
* @param bool $prepend Whether to prepend the autoloader or not.
*/
public static function registerBC($prepend = false)
{
/**
* register the class autoloader
*/
if (!defined('SMARTY_SPL_AUTOLOAD')) {
define('SMARTY_SPL_AUTOLOAD', 0);
}
if (SMARTY_SPL_AUTOLOAD && set_include_path(get_include_path() . PATH_SEPARATOR . SMARTY_SYSPLUGINS_DIR) !== false) {
$registeredAutoLoadFunctions = spl_autoload_functions();
if (!isset($registeredAutoLoadFunctions['spl_autoload'])) {
spl_autoload_register();
}
} else {
self::register($prepend);
}
}
/**
* Registers Smarty_Autoloader as an SPL autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not.
*/
public static function register($prepend = false)
{
self::$SMARTY_DIR = defined('SMARTY_DIR') ? SMARTY_DIR : dirname(__FILE__) . '/';
self::$SMARTY_SYSPLUGINS_DIR = defined('SMARTY_SYSPLUGINS_DIR') ? SMARTY_SYSPLUGINS_DIR : self::$SMARTY_DIR . 'sysplugins/';
if (version_compare(phpversion(), '5.3.0', '>=')) {
spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
} else {
spl_autoload_register(array(__CLASS__, 'autoload'));
}
}
/**
* Handles autoloading of classes.
*
* @param string $class A class name.
*/
public static function autoload($class)
{
// Request for Smarty or already unknown class
if (isset(self::$unknown[$class])) {
return;
}
$_class = strtolower($class);
if (isset(self::$syspluginsClasses[$_class])) {
$_class = (self::$syspluginsClasses[$_class] === true) ? $_class : self::$syspluginsClasses[$_class];
$file = self::$SMARTY_SYSPLUGINS_DIR . $_class . '.php';
require_once $file;
return;
} elseif (0 !== strpos($_class, 'smarty_internal_')) {
if (isset(self::$rootClasses[$class])) {
$file = self::$SMARTY_DIR . self::$rootClasses[$class];
require_once $file;
return;
}
self::$unknown[$class] = true;
return;
}
$file = self::$SMARTY_SYSPLUGINS_DIR . $_class . '.php';
if (is_file($file)) {
require_once $file;
return;
}
self::$unknown[$class] = true;
return;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -52,8 +52,6 @@ class SmartyBC extends Smarty
public function __construct(array $options = array())
{
parent::__construct($options);
// register {php} tag
$this->registerPlugin('block', 'php', 'smarty_php_tag');
}
/**
@ -115,10 +113,10 @@ class SmartyBC extends Smarty
/**
* Registers object to be used in templates
*
* @param string $object name of template object
* @param object $object_impl the referenced PHP object to register
* @param array $allowed list of allowed methods (empty = all)
* @param boolean $smarty_args smarty argument format, else traditional
* @param string $object name of template object
* @param object $object_impl the referenced PHP object to register
* @param array $allowed list of allowed methods (empty = all)
* @param boolean $smarty_args smarty argument format, else traditional
* @param array $block_methods list of methods that are block format
*
* @throws SmartyException
@ -448,20 +446,3 @@ class SmartyBC extends Smarty
trigger_error("Smarty error: $error_msg", $error_type);
}
}
/**
* Smarty {php}{/php} block function
*
* @param array $params parameter list
* @param string $content contents of the block
* @param object $template template object
* @param boolean &$repeat repeat flag
*
* @return string content re-formatted
*/
function smarty_php_tag($params, $content, $template, &$repeat)
{
eval($content);
return '';
}

View File

@ -5,7 +5,7 @@
<title>Smarty Debug Console</title>
<style type="text/css">
{literal}
body, h1, h2, td, th, p {
body, h1, h2, h3, td, th, p {
font-family: sans-serif;
font-weight: normal;
font-size: 0.9em;
@ -31,6 +31,13 @@
padding: 2px;
border-top: 1px solid black;
}
h3 {
text-align: left;
font-weight: bold;
color: black;
font-size: 0.7em;
padding: 2px;
}
body {
background: black;
@ -54,7 +61,6 @@
font-family: monospace;
vertical-align: top;
text-align: left;
width: 50%;
}
td {
@ -74,8 +80,20 @@
font-style: italic;
}
#bold div {
color: black;
font-weight: bold;
}
#blue h3 {
color: blue;
}
#normal div {
color: black;
font-weight: normal;
}
#table_assigned_vars th {
color: blue;
font-weight: bold;
}
#table_config_vars th {
@ -87,18 +105,17 @@
</head>
<body>
<h1>Smarty Debug Console
- {if isset($template_name)}{$template_name|debug_print_var nofilter}{else}Total Time {$execution_time|string_format:"%.5f"}{/if}</h1>
<h1>Smarty {Smarty::SMARTY_VERSION} Debug Console
- {if isset($template_name)}{$template_name|debug_print_var nofilter} {/if}{if !empty($template_data)}Total Time {$execution_time|string_format:"%.5f"}{/if}</h1>
{if !empty($template_data)}
<h2>included templates &amp; config files (load time in seconds)</h2>
<div>
{foreach $template_data as $template}
<font color=brown>{$template.name}</font>
<span class="exectime">
(compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"}
)
</span>
<br>&nbsp;&nbsp;<span class="exectime">
(compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"})
</span>
<br>
{/foreach}
</div>
@ -109,19 +126,24 @@
<table id="table_assigned_vars">
{foreach $assigned_vars as $vars}
<tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
<th>${$vars@key|escape:'html'}</th>
<td>{$vars|debug_print_var nofilter}</td>
</tr>
{/foreach}
<td><h3><font color=blue>${$vars@key}</font></h3>
{if isset($vars['nocache'])}<b>Nocache</b></br>{/if}
{if isset($vars['scope'])}<b>Origin:</b> {$vars['scope']|debug_print_var:10:80 nofilter}{/if}
</td>
<td><h3>Value</h3>{$vars['value']|debug_print_var:10:80 nofilter}</td>
<td>{if isset($vars['attributes'])}<h3>Attributes</h3>{$vars['attributes']|debug_print_var nofilter} {/if}</td>
{/foreach}
</table>
<h2>assigned config file variables (outer template scope)</h2>
<h2>assigned config file variables</h2>
<table id="table_config_vars">
{foreach $config_vars as $vars}
<tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
<th>{$vars@key|escape:'html'}</th>
<td>{$vars|debug_print_var nofilter}</td>
<td><h3><font color=blue>#{$vars@key}#</font></h3>
{if isset($vars['scope'])}<b>Origin:</b> {$vars['scope']|debug_print_var:10:80 nofilter}{/if}
</td>
<td>{$vars['value']|debug_print_var:10:80 nofilter}</td>
</tr>
{/foreach}
@ -130,8 +152,9 @@
</html>
{/capture}
<script type="text/javascript">
{$id = $template_name|default:''|md5}
_smarty_console = window.open("", "console{$id}", "width=680,height=600,resizable,scrollbars=yes");
{$id = ''}
{if $display_mode}{$id = "$offset$template_name"|md5}{/if}
_smarty_console = window.open("", "console{$id}", "width=680,height=600,left={$offset},top={$offset},resizable,scrollbars=yes");
_smarty_console.document.write("{$debug_output|escape:'javascript' nofilter}");
_smarty_console.document.close();
</script>

View File

@ -1,61 +0,0 @@
<?php
/**
* APC CacheResource for Smarty 3.1.x
*
* CacheResource Implementation based on the KeyValueStore API to use
* apc as the storage resource for Smarty's output caching.
*
*/
class Smarty_CacheResource_Apc extends Smarty_CacheResource_KeyValueStore {
public function __construct()
{
if(!function_exists('apc_cache_info'))
throw new Exception('APC Template Caching Error: APC is not installed');
}
/**
* Read values for a set of keys from cache
*
* @param array $keys list of keys to fetch
* @return array list of values with the given keys used as indexes
* @return boolean true on success, false on failure
*/
protected function read(array $keys)
{
return apc_fetch($keys);
}
/**
* Save values for a set of keys to cache
*
* @param array $keys list of values to save
* @param int $expire expiration time
* @return boolean true on success, false on failure
*/
protected function write(array $keys, $expire=null)
{
return apc_store($keys, null, $expire);
}
/**
* Remove values from cache
*
* @param array $keys list of keys to delete
* @return boolean true on success, false on failure
*/
protected function delete(array $keys)
{
foreach ($keys as $k) {
apc_delete($k);
}
return true;
}
/**
* Remove *all* values from cache
*
* @return boolean true on success, false on failure
*/
protected function purge()
{
return apc_clear_cache('user');
}
}

View File

@ -1,91 +0,0 @@
<?php
/**
* Memcache CacheResource for Smarty 3.1
*
* CacheResource Implementation based on the KeyValueStore API to use
* memcache as the storage resource for Smarty's output caching.
*
* Note that memcache has a limitation of 256 characters per cache-key.
* To avoid complications all cache-keys are translated to a sha1 hash.
*
* @package CacheResource-examples
* @author Rodney Rehm
*/
class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore {
/**
* memcache instance
* @var Memcache
*/
protected $memcache = null;
public function __construct()
{
$this->memcache = new Memcache();
$this->memcache->addServer( '127.0.0.1', 11211 );
}
/**
* Read values for a set of keys from cache
*
* @param array $keys list of keys to fetch
* @return array list of values with the given keys used as indexes
* @return boolean true on success, false on failure
*/
protected function read(array $keys)
{
$_keys = $lookup = array();
foreach ($keys as $k) {
$_k = sha1($k);
$_keys[] = $_k;
$lookup[$_k] = $k;
}
$_res = array();
$res = $this->memcache->get($_keys);
foreach ($res as $k => $v) {
$_res[$lookup[$k]] = $v;
}
return $_res;
}
/**
* Save values for a set of keys to cache
*
* @param array $keys list of values to save
* @param int $expire expiration time
* @return boolean true on success, false on failure
*/
protected function write(array $keys, $expire=null)
{
foreach ($keys as $k => $v) {
$k = sha1($k);
$this->memcache->set($k, $v, 0, $expire);
}
return true;
}
/**
* Remove values from cache
*
* @param array $keys list of keys to delete
* @return boolean true on success, false on failure
*/
protected function delete(array $keys)
{
foreach ($keys as $k) {
$k = sha1($k);
$this->memcache->delete($k);
}
return true;
}
/**
* Remove *all* values from cache
*
* @return boolean true on success, false on failure
*/
protected function purge()
{
return $this->memcache->flush();
}
}

View File

@ -33,7 +33,7 @@ function smarty_modifier_date_format($string, $format = null, $default_date = ''
$format = Smarty::$_DATE_FORMAT;
}
/**
* Include the {@link shared.make_timestamp.php} plugin
* require_once the {@link shared.make_timestamp.php} plugin
*/
require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php');
if ($string != '' && $string != '0000-00-00' && $string != '0000-00-00 00:00:00') {

View File

@ -14,26 +14,30 @@
*
* @author Monte Ohrt <monte at ohrt dot com>
*
* @param array|object $var variable to be formatted
* @param integer $depth maximum recursion depth if $var is an array
* @param integer $length maximum string length if $var is a string
* @param array|object $var variable to be formatted
* @param int $max maximum recursion depth if $var is an array or object
* @param int $length maximum string length if $var is a string
* @param int $depth actual recursion depth
* @param array $objects processed objects in actual depth to prevent recursive object processing
*
* @return string
*/
function smarty_modifier_debug_print_var($var, $depth = 0, $length = 40)
function smarty_modifier_debug_print_var($var, $max = 10, $length = 40, $depth = 0, $objects = array())
{
$_replace = array("\n" => '<i>\n</i>',
"\r" => '<i>\r</i>',
"\t" => '<i>\t</i>'
);
switch (gettype($var)) {
case 'array' :
$results = '<b>Array (' . count($var) . ')</b>';
if ($depth == $max) {
break;
}
foreach ($var as $curr_key => $curr_val) {
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
. '<b>' . strtr($curr_key, $_replace) . '</b> =&gt; '
. smarty_modifier_debug_print_var($curr_val, ++$depth, $length);
. smarty_modifier_debug_print_var($curr_val, $max, $length, ++ $depth, $objects);
$depth --;
}
break;
@ -41,10 +45,18 @@ function smarty_modifier_debug_print_var($var, $depth = 0, $length = 40)
case 'object' :
$object_vars = get_object_vars($var);
$results = '<b>' . get_class($var) . ' Object (' . count($object_vars) . ')</b>';
if (in_array($var, $objects)) {
$results .= ' called recursive';
break;
}
if ($depth == $max) {
break;
}
$objects[] = $var;
foreach ($object_vars as $curr_key => $curr_val) {
$results .= '<br>' . str_repeat('&nbsp;', $depth * 2)
. '<b> -&gt;' . strtr($curr_key, $_replace) . '</b> = '
. smarty_modifier_debug_print_var($curr_val, ++$depth, $length);
. smarty_modifier_debug_print_var($curr_val, $max, $length, ++ $depth, $objects);
$depth --;
}
break;

View File

@ -45,7 +45,7 @@ function smarty_outputfilter_trimwhitespace($source)
// capture html elements not to be messed with
$_offset = 0;
if (preg_match_all('#<(script|pre|textarea)[^>]*>.*?</\\1>#is', $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
if (preg_match_all('#(<script[^>]*>.*?</script[^>]*>)|(<textarea[^>]*>.*?</textarea[^>]*>)|(<pre[^>]*>.*?</pre[^>]*>)#is', $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
foreach ($matches as $match) {
$store[] = $match[0][0];
$_length = strlen($match[0][0]);
@ -62,7 +62,7 @@ function smarty_outputfilter_trimwhitespace($source)
// can't remove them entirely, becaue that might break poorly implemented CSS display:inline-block elements
'#(:SMARTY@!@|>)\s+(?=@!@SMARTY:|<)#s' => '\1 \2',
// remove spaces between attributes (but not in attribute values!)
'#(([a-z0-9]\s*=\s*(["\'])[^\3]*?\3)|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \4',
'#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5',
// note: for some very weird reason trim() seems to remove spaces inside attributes.
// maybe a \0 byte or something is interfering?
'#^\s+<#Ss' => '<',

View File

@ -15,20 +15,13 @@
*/
abstract class Smarty_CacheResource
{
/**
* cache for Smarty_CacheResource instances
*
* @var array
*/
public static $resources = array();
/**
* resource types provided by the core
*
* @var array
*/
protected static $sysplugins = array(
'file' => true,
'file' => 'smarty_internal_cacheresource_file.php',
);
/**
@ -204,21 +197,16 @@ abstract class Smarty_CacheResource
}
// try sysplugins dir
if (isset(self::$sysplugins[$type])) {
if (!isset(self::$resources[$type])) {
$cache_resource_class = 'Smarty_Internal_CacheResource_' . ucfirst($type);
self::$resources[$type] = new $cache_resource_class();
$cache_resource_class = 'Smarty_Internal_CacheResource_' . ucfirst($type);
if (!class_exists($cache_resource_class, false)) {
require SMARTY_SYSPLUGINS_DIR . self::$sysplugins[$type];
}
return $smarty->_cacheresource_handlers[$type] = self::$resources[$type];
return $smarty->_cacheresource_handlers[$type] = new $cache_resource_class();
}
// try plugins dir
$cache_resource_class = 'Smarty_CacheResource_' . ucfirst($type);
if ($smarty->loadPlugin($cache_resource_class)) {
if (!isset(self::$resources[$type])) {
self::$resources[$type] = new $cache_resource_class();
}
return $smarty->_cacheresource_handlers[$type] = self::$resources[$type];
return $smarty->_cacheresource_handlers[$type] = new $cache_resource_class();
}
// give up
throw new SmartyException("Unable to load cache resource '{$type}'");
@ -239,204 +227,3 @@ abstract class Smarty_CacheResource
}
}
}
/**
* Smarty Resource Data Object
* Cache Data Container for Template Files
*
* @package Smarty
* @subpackage TemplateResources
* @author Rodney Rehm
*/
class Smarty_Template_Cached
{
/**
* Source Filepath
*
* @var string
*/
public $filepath = false;
/**
* Source Content
*
* @var string
*/
public $content = null;
/**
* Source Timestamp
*
* @var integer
*/
public $timestamp = false;
/**
* Source Existence
*
* @var boolean
*/
public $exists = false;
/**
* Cache Is Valid
*
* @var boolean
*/
public $valid = false;
/**
* Cache was processed
*
* @var boolean
*/
public $processed = false;
/**
* CacheResource Handler
*
* @var Smarty_CacheResource
*/
public $handler = null;
/**
* Template Compile Id (Smarty_Internal_Template::$compile_id)
*
* @var string
*/
public $compile_id = null;
/**
* Template Cache Id (Smarty_Internal_Template::$cache_id)
*
* @var string
*/
public $cache_id = null;
/**
* Id for cache locking
*
* @var string
*/
public $lock_id = null;
/**
* flag that cache is locked by this instance
*
* @var bool
*/
public $is_locked = false;
/**
* Source Object
*
* @var Smarty_Template_Source
*/
public $source = null;
/**
* create Cached Object container
*
* @param Smarty_Internal_Template $_template template object
*/
public function __construct(Smarty_Internal_Template $_template)
{
$this->compile_id = $_template->compile_id;
$this->cache_id = $_template->cache_id;
$this->source = $_template->source;
$_template->cached = $this;
$smarty = $_template->smarty;
//
// load resource handler
//
$this->handler = $handler = Smarty_CacheResource::load($smarty); // Note: prone to circular references
//
// check if cache is valid
//
if (!($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || $_template->caching == Smarty::CACHING_LIFETIME_SAVED) || $_template->source->recompiled) {
$handler->populate($this, $_template);
return;
}
while (true) {
while (true) {
$handler->populate($this, $_template);
if ($this->timestamp === false || $smarty->force_compile || $smarty->force_cache) {
$this->valid = false;
} else {
$this->valid = true;
}
if ($this->valid && $_template->caching == Smarty::CACHING_LIFETIME_CURRENT && $_template->cache_lifetime >= 0 && time() > ($this->timestamp + $_template->cache_lifetime)) {
// lifetime expired
$this->valid = false;
}
if ($this->valid || !$_template->smarty->cache_locking) {
break;
}
if (!$this->handler->locked($_template->smarty, $this)) {
$this->handler->acquireLock($_template->smarty, $this);
break 2;
}
}
if ($this->valid) {
if (!$_template->smarty->cache_locking || $this->handler->locked($_template->smarty, $this) === null) {
// load cache file for the following checks
if ($smarty->debugging) {
Smarty_Internal_Debug::start_cache($_template);
}
if ($handler->process($_template, $this) === false) {
$this->valid = false;
} else {
$this->processed = true;
}
if ($smarty->debugging) {
Smarty_Internal_Debug::end_cache($_template);
}
} else {
continue;
}
} else {
return;
}
if ($this->valid && $_template->caching === Smarty::CACHING_LIFETIME_SAVED && $_template->properties['cache_lifetime'] >= 0 && (time() > ($_template->cached->timestamp + $_template->properties['cache_lifetime']))) {
$this->valid = false;
}
if (!$this->valid && $_template->smarty->cache_locking) {
$this->handler->acquireLock($_template->smarty, $this);
return;
} else {
return;
}
}
}
/**
* Write this cache object to handler
*
* @param Smarty_Internal_Template $_template template object
* @param string $content content to cache
*
* @return boolean success
*/
public function write(Smarty_Internal_Template $_template, $content)
{
if (!$_template->source->recompiled) {
if ($this->handler->writeCachedContent($_template, $content)) {
$this->content = null;
$this->timestamp = time();
$this->exists = true;
$this->valid = true;
if ($_template->smarty->cache_locking) {
$this->handler->releaseLock($_template->smarty, $this);
}
return true;
}
}
return false;
}
}

View File

@ -84,8 +84,11 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
{
$_cache_id = isset($cached->cache_id) ? preg_replace('![^\w\|]+!', '_', $cached->cache_id) : null;
$_compile_id = isset($cached->compile_id) ? preg_replace('![^\w\|]+!', '_', $cached->compile_id) : null;
$cached->filepath = sha1($cached->source->filepath . $_cache_id . $_compile_id);
$path = $cached->source->filepath . $_cache_id . $_compile_id;
$cached->filepath = sha1($path);
if ($_template->smarty->cache_locking) {
$cached->lock_id = sha1('lock.' . $path);
}
$this->populateTimestamp($cached);
}
@ -169,6 +172,34 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
);
}
/**
* Read cached template from cache
*
* @param Smarty_Internal_Template $_template template object
*
* @return string content
*/
public function readCachedContent(Smarty_Internal_Template $_template)
{
$content = $_template->cached->content ? $_template->cached->content : null;
$timestamp = null;
if ($content === null) {
$timestamp = null;
$this->fetch(
$_template->cached->filepath,
$_template->source->name,
$_template->cache_id,
$_template->compile_id,
$content,
$timestamp
);
}
if (isset($content)) {
return $content;
}
return false;
}
/**
* Empty cache
*
@ -238,15 +269,14 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
*/
public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
{
$id = $cached->filepath;
$id = $cached->lock_id;
$name = $cached->source->name . '.lock';
$mtime = $this->fetchTimestamp($id, $name, null, null);
$mtime = $this->fetchTimestamp($id, $name, $cached->cache_id, $cached->compile_id);
if ($mtime === null) {
$this->fetch($id, $name, null, null, $content, $mtime);
$this->fetch($id, $name, $cached->cache_id, $cached->compile_id, $content, $mtime);
}
return $mtime && time() - $mtime < $smarty->locking_timeout;
return $mtime && ($t = time()) - $mtime < $smarty->locking_timeout;
}
/**
@ -260,10 +290,9 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached)
{
$cached->is_locked = true;
$id = $cached->filepath;
$id = $cached->lock_id;
$name = $cached->source->name . '.lock';
$this->save($id, $name, null, null, $smarty->locking_timeout, '');
$this->save($id, $name, $cached->cache_id, $cached->compile_id, $smarty->locking_timeout, '');
}
/**
@ -277,8 +306,7 @@ abstract class Smarty_CacheResource_Custom extends Smarty_CacheResource
public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached)
{
$cached->is_locked = false;
$name = $cached->source->name . '.lock';
$this->delete($name, null, null, null);
$this->delete($name, $cached->cache_id, $cached->compile_id, null);
}
}

View File

@ -36,6 +36,7 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
* @var array
*/
protected $contents = array();
/**
* cache for timestamps
*
@ -53,10 +54,7 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
*/
public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template)
{
$cached->filepath = $_template->source->uid
. '#' . $this->sanitize($cached->source->resource)
. '#' . $this->sanitize($cached->cache_id)
. '#' . $this->sanitize($cached->compile_id);
$cached->filepath = $_template->source->uid . '#' . $this->sanitize($cached->source->resource) . '#' . $this->sanitize($cached->cache_id) . '#' . $this->sanitize($cached->compile_id);
$this->populateTimestamp($cached);
}
@ -126,6 +124,28 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
return $this->write(array($_template->cached->filepath => $content), $_template->properties['cache_lifetime']);
}
/**
* Read cached template from cache
*
* @param Smarty_Internal_Template $_template template object
*
* @return string content
*/
public function readCachedContent(Smarty_Internal_Template $_template)
{
$content = $_template->cached->content ? $_template->cached->content : null;
$timestamp = null;
if ($content === null) {
if (!$this->fetch($_template->cached->filepath, $_template->source->name, $_template->cache_id, $_template->compile_id, $content, $timestamp, $_template->source->uid)) {
return false;
}
}
if (isset($content)) {
return $content;
}
return false;
}
/**
* Empty cache
* {@internal the $exp_time argument is ignored altogether }}
@ -275,11 +295,8 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource
*/
protected function getMetaTimestamp(&$content)
{
$s = unpack("N", substr($content, 0, 4));
$m = unpack("N", substr($content, 4, 4));
$content = substr($content, 8);
return $s[1] + ($m[1] / 100000000);
extract(unpack('N1s/N1m/a*content', $content));
return $s + ($m / 100000000);
}
/**

View File

@ -1,94 +0,0 @@
<?php
/**
* Smarty Internal Plugin
*
* @package Smarty
* @subpackage TemplateResources
*/
/**
* Smarty Resource Data Object
* Meta Data Container for Config Files
*
* @package Smarty
* @subpackage TemplateResources
* @author Rodney Rehm
* @property string $content
* @property int $timestamp
* @property bool $exists
*/
class Smarty_Config_Source extends Smarty_Template_Source
{
/**
* create Config Object container
*
* @param Smarty_Resource $handler Resource Handler this source object communicates with
* @param Smarty $smarty Smarty instance this source object belongs to
* @param string $resource full config_resource
* @param string $type type of resource
* @param string $name resource name
* @param string $unique_resource unqiue resource name
*/
public function __construct(Smarty_Resource $handler, Smarty $smarty, $resource, $type, $name, $unique_resource)
{
$this->handler = $handler; // Note: prone to circular references
// Note: these may be ->config_compiler_class etc in the future
//$this->config_compiler_class = $handler->config_compiler_class;
//$this->config_lexer_class = $handler->config_lexer_class;
//$this->config_parser_class = $handler->config_parser_class;
$this->smarty = $smarty;
$this->resource = $resource;
$this->type = $type;
$this->name = $name;
$this->unique_resource = $unique_resource;
}
/**
* <<magic>> Generic setter.
*
* @param string $property_name valid: content, timestamp, exists
* @param mixed $value newly assigned value (not check for correct type)
*
* @throws SmartyException when the given property name is not valid
*/
public function __set($property_name, $value)
{
switch ($property_name) {
case 'content':
case 'timestamp':
case 'exists':
$this->$property_name = $value;
break;
default:
throw new SmartyException("invalid config property '$property_name'.");
}
}
/**
* <<magic>> Generic getter.
*
* @param string $property_name valid: content, timestamp, exists
*
* @return mixed|void
* @throws SmartyException when the given property name is not valid
*/
public function __get($property_name)
{
switch ($property_name) {
case 'timestamp':
case 'exists':
$this->handler->populateTimestamp($this);
return $this->$property_name;
case 'content':
return $this->content = $this->handler->getContent($this);
default:
throw new SmartyException("config property '$property_name' does not exist.");
}
}
}

View File

@ -0,0 +1,66 @@
<?php
/**
* Smarty Plugin Data
* This file contains the data object
*
* @package Smarty
* @subpackage Template
* @author Uwe Tews
*/
/**
* class for the Smarty data object
* The Smarty data object will hold Smarty variables in the current scope
*
* @package Smarty
* @subpackage Template
*/
class Smarty_Data extends Smarty_Internal_Data
{
/**
* Counter
*
* @var int
*/
static $count = 0;
/**
* Data block name
*
* @var string
*/
public $dataObjectName = '';
/**
* Smarty object
*
* @var Smarty
*/
public $smarty = null;
/**
* create Smarty data object
*
* @param Smarty|array $_parent parent template
* @param Smarty|Smarty_Internal_Template $smarty global smarty instance
* @param string $name optional data block name
*
* @throws SmartyException
*/
public function __construct($_parent = null, $smarty = null, $name = null)
{
self::$count ++;
$this->dataObjectName = 'Data_object ' . (isset($name) ? "'{$name}'" : self::$count);
$this->smarty = $smarty;
if (is_object($_parent)) {
// when object set up back pointer
$this->parent = $_parent;
} elseif (is_array($_parent)) {
// set up variable values
foreach ($_parent as $_key => $_val) {
$this->tpl_vars[$_key] = new Smarty_Variable($_val);
}
} elseif ($_parent != null) {
throw new SmartyException("Wrong type for template variables");
}
}
}

View File

@ -61,8 +61,10 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
$cached->lock_id = $_lock_dir . sha1($_cache_id . $_compile_id . $_template->source->uid) . '.lock';
}
$cached->filepath = $_cache_dir . $_cache_id . $_compile_id . $_filepath . '.' . basename($_source_file_path) . '.php';
$cached->timestamp = @filemtime($cached->filepath);
$cached->exists = !!$cached->timestamp;
$cached->timestamp = $cached->exists = is_file($cached->filepath);
if ($cached->exists) {
$cached->timestamp = filemtime($cached->filepath);
}
}
/**
@ -74,8 +76,10 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
*/
public function populateTimestamp(Smarty_Template_Cached $cached)
{
$cached->timestamp = @filemtime($cached->filepath);
$cached->exists = !!$cached->timestamp;
$cached->timestamp = $cached->exists = is_file($cached->filepath);
if ($cached->exists) {
$cached->timestamp = filemtime($cached->filepath);
}
}
/**
@ -106,14 +110,30 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
*/
public function writeCachedContent(Smarty_Internal_Template $_template, $content)
{
if (Smarty_Internal_Write_File::writeFile($_template->cached->filepath, $content, $_template->smarty) === true) {
$_template->cached->timestamp = @filemtime($_template->cached->filepath);
$_template->cached->exists = !!$_template->cached->timestamp;
if ($_template->cached->exists) {
$obj = new Smarty_Internal_Write_File();
if ($obj->writeFile($_template->cached->filepath, $content, $_template->smarty) === true) {
$cached = $_template->cached;
$cached->timestamp = $cached->exists = is_file($cached->filepath);
if ($cached->exists) {
$cached->timestamp = filemtime($cached->filepath);
return true;
}
}
return false;
}
/**
* Read cached template from cache
*
* @param Smarty_Internal_Template $_template template object
*
* @return string content
*/
public function readCachedContent(Smarty_Internal_Template $_template)
{
if (is_file($_template->cached->filepath)) {
return file_get_contents($_template->cached->filepath);
}
return false;
}
@ -262,9 +282,12 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
} else {
clearstatcache();
}
$t = @filemtime($cached->lock_id);
return $t && (time() - $t < $smarty->locking_timeout);
if (is_file($cached->lock_id)) {
$t = @filemtime($cached->lock_id);
return $t && (time() - $t < $smarty->locking_timeout);
} else {
return false;
}
}
/**

View File

@ -42,7 +42,7 @@ class Smarty_Internal_Compile_Assign extends Smarty_Internal_CompileBase
if (isset($compiler->template->tpl_vars[trim($_attr['var'], "'")])) {
$compiler->template->tpl_vars[trim($_attr['var'], "'")]->nocache = true;
} else {
$compiler->template->tpl_vars[trim($_attr['var'], "'")] = new Smarty_variable(null, true);
$compiler->template->tpl_vars[trim($_attr['var'], "'")] = new Smarty_Variable(null, true);
}
}
// scope setup
@ -66,9 +66,9 @@ class Smarty_Internal_Compile_Assign extends Smarty_Internal_CompileBase
if ($compiler->template->smarty instanceof SmartyBC) {
$output = "<?php if (isset(\$_smarty_tpl->tpl_vars[$_attr[var]])) {\$_smarty_tpl->tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]];";
$output .= "\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value = $_attr[value]; \$_smarty_tpl->tpl_vars[$_attr[var]]->nocache = $_nocache; \$_smarty_tpl->tpl_vars[$_attr[var]]->scope = $_scope;";
$output .= "\n} else \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_variable($_attr[value], $_nocache, $_scope);";
$output .= "\n} else \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_Variable($_attr[value], $_nocache, $_scope);";
} else {
$output = "<?php \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_variable($_attr[value], $_nocache, $_scope);";
$output = "<?php \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_Variable($_attr[value], $_nocache, $_scope);";
}
}
if ($_scope == Smarty::SCOPE_PARENT) {

View File

@ -113,7 +113,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase
$compiler->inheritance = true;
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
$compiler->parser->current_buffer = new _smarty_template_buffer($compiler->parser);
$compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template($compiler->parser);
$compiler->has_code = false;
return true;
@ -143,7 +143,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase
// if called by {$smarty.block.child} we must search the name of enclosing {block}
if ($_name == null) {
$stack_count = count($compiler->_tag_stack);
while (--$stack_count >= 0) {
while (-- $stack_count >= 0) {
if ($compiler->_tag_stack[$stack_count][0] == 'block') {
$_name = trim($compiler->_tag_stack[$stack_count][1][0]['name'], "\"'");
break;
@ -173,20 +173,18 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase
$_tpl->compiler->suppressHeader = true;
$_tpl->compiler->suppressFilter = true;
$_tpl->compiler->suppressTemplatePropertyHeader = true;
$_tpl->compiler->suppressMergedTemplates = true;
$nocache = $compiler->nocache || $compiler->tag_nocache;
if (strpos($compiler->template->block_data[$_name]['source'], self::parent) !== false) {
$_output = str_replace(self::parent, $compiler->parser->current_buffer->to_smarty_php(), $_tpl->compiler->compileTemplate($_tpl, $nocache));
$_output = str_replace(self::parent, $compiler->parser->current_buffer->to_smarty_php(), $_tpl->compiler->compileTemplate($_tpl, $nocache, $compiler->parent_compiler));
} elseif ($compiler->template->block_data[$_name]['mode'] == 'prepend') {
$_output = $_tpl->compiler->compileTemplate($_tpl, $nocache) . $compiler->parser->current_buffer->to_smarty_php();
$_output = $_tpl->compiler->compileTemplate($_tpl, $nocache, $compiler->parent_compiler) . $compiler->parser->current_buffer->to_smarty_php();
} elseif ($compiler->template->block_data[$_name]['mode'] == 'append') {
$_output = $compiler->parser->current_buffer->to_smarty_php() . $_tpl->compiler->compileTemplate($_tpl, $nocache);
$_output = $compiler->parser->current_buffer->to_smarty_php() . $_tpl->compiler->compileTemplate($_tpl, $nocache, $compiler->parent_compiler);
} elseif (!empty($compiler->template->block_data[$_name])) {
$_output = $_tpl->compiler->compileTemplate($_tpl, $nocache);
$_output = $_tpl->compiler->compileTemplate($_tpl, $nocache, $compiler->parent_compiler);
}
$compiler->template->properties['file_dependency'] = array_merge($compiler->template->properties['file_dependency'], $_tpl->properties['file_dependency']);
$compiler->template->properties['function'] = array_merge($compiler->template->properties['function'], $_tpl->properties['function']);
$compiler->merged_templates = array_merge($compiler->merged_templates, $_tpl->compiler->merged_templates);
$compiler->template->properties['tpl_function'] = array_merge($compiler->template->properties['tpl_function'], $_tpl->properties['tpl_function']);
$compiler->template->variable_filters = $_tpl->variable_filters;
if ($_tpl->has_nocache_code) {
$compiler->template->has_nocache_code = true;
@ -221,7 +219,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase
// if called by {$smarty.block.parent} we must search the name of enclosing {block}
if ($_name == null) {
$stack_count = count($compiler->_tag_stack);
while (--$stack_count >= 0) {
while (-- $stack_count >= 0) {
if ($compiler->_tag_stack[$stack_count][0] == 'block') {
$_name = trim($compiler->_tag_stack[$stack_count][1][0]['name'], "\"'");
break;
@ -245,7 +243,6 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase
*
* @param $compiler
* @param string $source source text
*
*/
static function blockSource($compiler, $source)
{
@ -337,7 +334,9 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase
$_output = $compiler->parser->current_buffer->to_smarty_php();
}
}
unset($compiler->template->block_data[$_name]['compiled']);
if (isset($compiler->template->block_data[$_name]['compiled'])) {
unset($compiler->template->block_data[$_name]['compiled']);
}
// reset flags
$compiler->parser->current_buffer = $saved_data[2];
if ($compiler->nocache) {

View File

@ -55,13 +55,11 @@ class Smarty_Internal_Compile_Call extends Smarty_Internal_CompileBase
// output will be stored in a smarty variable instead of being displayed
$_assign = $_attr['assign'];
}
//$_name = trim($_attr['name'], "'\"");
$_name = $_attr['name'];
if ($compiler->compiles_template_function) {
$compiler->called_functions[] = trim($_name, "'\"");
}
unset($_attr['name'], $_attr['assign'], $_attr['nocache']);
// set flag (compiled code of {function} must be included in cache file
if ($compiler->nocache || $compiler->tag_nocache) {
if (!$compiler->template->caching || $compiler->nocache || $compiler->tag_nocache) {
$_nocache = 'true';
} else {
$_nocache = 'false';
@ -74,54 +72,14 @@ class Smarty_Internal_Compile_Call extends Smarty_Internal_CompileBase
$_paramsArray[] = "'$_key'=>$_value";
}
}
if (isset($compiler->template->properties['function'][$_name]['parameter'])) {
foreach ($compiler->template->properties['function'][$_name]['parameter'] as $_key => $_value) {
if (!isset($_attr[$_key])) {
if (is_int($_key)) {
$_paramsArray[] = "$_key=>$_value";
} else {
$_paramsArray[] = "'$_key'=>$_value";
}
}
}
} elseif (isset($compiler->smarty->template_functions[$_name]['parameter'])) {
foreach ($compiler->smarty->template_functions[$_name]['parameter'] as $_key => $_value) {
if (!isset($_attr[$_key])) {
if (is_int($_key)) {
$_paramsArray[] = "$_key=>$_value";
} else {
$_paramsArray[] = "'$_key'=>$_value";
}
}
}
}
//variable name?
if (!(strpos($_name, '$') === false)) {
$call_cache = $_name;
$call_function = '$tmp = "smarty_template_function_".' . $_name . '; $tmp';
} else {
$_name = trim($_name, "'\"");
$call_cache = "'{$_name}'";
$call_function = 'smarty_template_function_' . $_name;
}
$_params = 'array(' . implode(",", $_paramsArray) . ')';
$_hash = str_replace('-', '_', $compiler->template->properties['nocache_hash']);
//$compiler->suppressNocacheProcessing = true;
// was there an assign attribute
if (isset($_assign)) {
if ($compiler->template->caching) {
$_output = "<?php ob_start(); Smarty_Internal_Function_Call_Handler::call ({$call_cache},\$_smarty_tpl,{$_params},'{$_hash}',{$_nocache}); \$_smarty_tpl->assign({$_assign}, ob_get_clean());?>\n";
} else {
$_output = "<?php ob_start(); {$call_function}(\$_smarty_tpl,{$_params}); \$_smarty_tpl->assign({$_assign}, ob_get_clean());?>\n";
}
$_output = "<?php ob_start();\$_smarty_tpl->callTemplateFunction ({$_name}, \$_smarty_tpl, {$_params}, {$_nocache}); \$_smarty_tpl->assign({$_assign}, ob_get_clean());?>\n";
} else {
if ($compiler->template->caching) {
$_output = "<?php Smarty_Internal_Function_Call_Handler::call ({$call_cache},\$_smarty_tpl,{$_params},'{$_hash}',{$_nocache});?>\n";
} else {
$_output = "<?php {$call_function}(\$_smarty_tpl,{$_params});?>\n";
}
$_output = "<?php \$_smarty_tpl->callTemplateFunction ({$_name}, \$_smarty_tpl, {$_params}, {$_nocache});?>\n";
}
return $_output;
}
}

View File

@ -74,8 +74,7 @@ class Smarty_Internal_Compile_Config_Load extends Smarty_Internal_CompileBase
}
}
// create config object
$_output = "<?php \$_config = new Smarty_Internal_Config($conf_file, \$_smarty_tpl->smarty, \$_smarty_tpl);";
$_output .= "\$_config->loadConfigVars($section, '$scope'); ?>";
$_output = "<?php Smarty_Internal_Extension_Config::configLoad(\$_smarty_tpl, $conf_file, $section, '$scope');?>";
return $_output;
}

View File

@ -47,27 +47,48 @@ class Smarty_Internal_Compile_For extends Smarty_Internal_CompileBase
$output = "<?php ";
if ($parameter == 1) {
foreach ($_attr['start'] as $_statement) {
$output .= " \$_smarty_tpl->tpl_vars[$_statement[var]] = new Smarty_Variable;";
$output .= " \$_smarty_tpl->tpl_vars[$_statement[var]]->value = $_statement[value];\n";
if (is_array($_statement['var'])) {
$var = $_statement['var']['var'];
$index = $_statement['var']['smarty_internal_index'];
} else {
$var = $_statement['var'];
$index = '';
}
$output .= " \$_smarty_tpl->tpl_vars[$var] = new Smarty_Variable;";
$output .= " \$_smarty_tpl->tpl_vars[$var]->value{$index} = $_statement[value];\n";
}
$output .= " if ($_attr[ifexp]) { for (\$_foo=true;$_attr[ifexp]; \$_smarty_tpl->tpl_vars[$_attr[var]]->value$_attr[step]) {\n";
if (is_array($_attr['var'])) {
$var = $_attr['var']['var'];
$index = $_attr['var']['smarty_internal_index'];
} else {
$var = $_attr['var'];
$index = '';
}
$output .= " if ($_attr[ifexp]) { for (\$_foo=true;$_attr[ifexp]; \$_smarty_tpl->tpl_vars[$var]->value{$index}$_attr[step]) {\n";
} else {
$_statement = $_attr['start'];
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]] = new Smarty_Variable;";
if (isset($_attr['step'])) {
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]]->step = $_attr[step];";
if (is_array($_statement['var'])) {
$var = $_statement['var']['var'];
$index = $_statement['var']['smarty_internal_index'];
} else {
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]]->step = 1;";
$var = $_statement['var'];
$index = '';
}
$output .= "\$_smarty_tpl->tpl_vars[$var] = new Smarty_Variable;";
if (isset($_attr['step'])) {
$output .= "\$_smarty_tpl->tpl_vars[$var]->step = $_attr[step];";
} else {
$output .= "\$_smarty_tpl->tpl_vars[$var]->step = 1;";
}
if (isset($_attr['max'])) {
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]]->total = (int) min(ceil((\$_smarty_tpl->tpl_vars[$_statement[var]]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$_statement[var]]->step)),$_attr[max]);\n";
$output .= "\$_smarty_tpl->tpl_vars[$var]->total = (int) min(ceil((\$_smarty_tpl->tpl_vars[$var]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$var]->step)),$_attr[max]);\n";
} else {
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]]->total = (int) ceil((\$_smarty_tpl->tpl_vars[$_statement[var]]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$_statement[var]]->step));\n";
$output .= "\$_smarty_tpl->tpl_vars[$var]->total = (int) ceil((\$_smarty_tpl->tpl_vars[$var]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$var]->step));\n";
}
$output .= "if (\$_smarty_tpl->tpl_vars[$_statement[var]]->total > 0) {\n";
$output .= "for (\$_smarty_tpl->tpl_vars[$_statement[var]]->value = $_statement[value], \$_smarty_tpl->tpl_vars[$_statement[var]]->iteration = 1;\$_smarty_tpl->tpl_vars[$_statement[var]]->iteration <= \$_smarty_tpl->tpl_vars[$_statement[var]]->total;\$_smarty_tpl->tpl_vars[$_statement[var]]->value += \$_smarty_tpl->tpl_vars[$_statement[var]]->step, \$_smarty_tpl->tpl_vars[$_statement[var]]->iteration++) {\n";
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]]->first = \$_smarty_tpl->tpl_vars[$_statement[var]]->iteration == 1;";
$output .= "\$_smarty_tpl->tpl_vars[$_statement[var]]->last = \$_smarty_tpl->tpl_vars[$_statement[var]]->iteration == \$_smarty_tpl->tpl_vars[$_statement[var]]->total;";
$output .= "if (\$_smarty_tpl->tpl_vars[$var]->total > 0) {\n";
$output .= "for (\$_smarty_tpl->tpl_vars[$var]->value{$index} = $_statement[value], \$_smarty_tpl->tpl_vars[$var]->iteration = 1;\$_smarty_tpl->tpl_vars[$var]->iteration <= \$_smarty_tpl->tpl_vars[$var]->total;\$_smarty_tpl->tpl_vars[$var]->value{$index} += \$_smarty_tpl->tpl_vars[$var]->step, \$_smarty_tpl->tpl_vars[$var]->iteration++) {\n";
$output .= "\$_smarty_tpl->tpl_vars[$var]->first = \$_smarty_tpl->tpl_vars[$var]->iteration == 1;";
$output .= "\$_smarty_tpl->tpl_vars[$var]->last = \$_smarty_tpl->tpl_vars[$var]->iteration == \$_smarty_tpl->tpl_vars[$var]->total;";
}
$output .= "?>";

View File

@ -64,103 +64,152 @@ class Smarty_Internal_Compile_Foreach extends Smarty_Internal_CompileBase
$key = null;
}
$this->openTag($compiler, 'foreach', array('foreach', $compiler->nocache, $item, $key));
$this->openTag($compiler, 'foreach', array('foreach', $compiler->nocache, $item, $key, true));
// maybe nocache because of nocache variables
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
if (isset($_attr['name'])) {
$name = $_attr['name'];
$name = trim($_attr['name'], '\'"');
$has_name = true;
$SmartyVarName = '$smarty.foreach.' . trim($name, '\'"') . '.';
$SmartyVarName = "\$smarty.foreach.{$name}.";
} else {
$name = null;
$has_name = false;
}
$ItemVarName = '$' . trim($item, '\'"') . '@';
// evaluates which Smarty variables and properties have to be computed
if ($has_name) {
$usesSmartyFirst = strpos($compiler->lex->data, $SmartyVarName . 'first') !== false;
$usesSmartyLast = strpos($compiler->lex->data, $SmartyVarName . 'last') !== false;
$usesSmartyIndex = strpos($compiler->lex->data, $SmartyVarName . 'index') !== false;
$usesSmartyIteration = strpos($compiler->lex->data, $SmartyVarName . 'iteration') !== false;
$usesSmartyShow = strpos($compiler->lex->data, $SmartyVarName . 'show') !== false;
$usesSmartyTotal = strpos($compiler->lex->data, $SmartyVarName . 'total') !== false;
$useSmartyForeach = $usesSmartyFirst = strpos($compiler->lex->data, $SmartyVarName . 'first') !== false;
$useSmartyForeach = ($usesSmartyLast = strpos($compiler->lex->data, $SmartyVarName . 'last') !== false) || $useSmartyForeach;
$useSmartyForeach = ($usesSmartyIndex = strpos($compiler->lex->data, $SmartyVarName . 'index') !== false) || $useSmartyForeach;
$useSmartyForeach = ($usesSmartyIteration = (!$usesSmartyIndex && ($usesSmartyFirst || $usesSmartyLast)) || strpos($compiler->lex->data, $SmartyVarName . 'iteration') !== false) || $useSmartyForeach;
$useSmartyForeach = ($usesSmartyShow = strpos($compiler->lex->data, $SmartyVarName . 'show') !== false) || $useSmartyForeach;
$useSmartyForeach = ($usesSmartyTotal = $usesSmartyLast ||strpos($compiler->lex->data, $SmartyVarName . 'total') !== false) || $useSmartyForeach;
} else {
$usesSmartyFirst = false;
$usesSmartyLast = false;
$usesSmartyTotal = false;
$usesSmartyShow = false;
$useSmartyForeach = false;
}
$usesPropFirst = $usesSmartyFirst || strpos($compiler->lex->data, $ItemVarName . 'first') !== false;
$usesPropLast = $usesSmartyLast || strpos($compiler->lex->data, $ItemVarName . 'last') !== false;
$usesPropIndex = $usesPropFirst || strpos($compiler->lex->data, $ItemVarName . 'index') !== false;
$usesPropIteration = $usesPropLast || strpos($compiler->lex->data, $ItemVarName . 'iteration') !== false;
$usesPropKey = strpos($compiler->lex->data, $ItemVarName . 'key') !== false;
$usesPropFirst = strpos($compiler->lex->data, $ItemVarName . 'first') !== false;
$usesPropLast = strpos($compiler->lex->data, $ItemVarName . 'last') !== false;
$usesPropIndex = strpos($compiler->lex->data, $ItemVarName . 'index') !== false;
$usesPropIteration = (!$usesPropIndex && ($usesPropFirst || $usesPropLast)) || strpos($compiler->lex->data, $ItemVarName . 'iteration') !== false;
$usesPropShow = strpos($compiler->lex->data, $ItemVarName . 'show') !== false;
$usesPropTotal = $usesSmartyTotal || $usesSmartyShow || $usesPropShow || $usesPropLast || strpos($compiler->lex->data, $ItemVarName . 'total') !== false;
// generate output code
$output = "<?php ";
$output .= " \$_smarty_tpl->tpl_vars[$item] = new Smarty_Variable; \$_smarty_tpl->tpl_vars[$item]->_loop = false;\n";
if ($key != null) {
$output .= " \$_smarty_tpl->tpl_vars[$key] = new Smarty_Variable;\n";
$usesPropTotal = $usesPropLast || strpos($compiler->lex->data, $ItemVarName . 'total') !== false;
$keyTerm = '';
if ($usesPropKey) {
$keyTerm = "\$_smarty_tpl->tpl_vars[$item]->key => ";
} elseif ($key != null) {
$keyTerm = "\$_smarty_tpl->tpl_vars[$key]->value => ";
}
// generate output code
$output = "<?php\n";
$output .= "\$_from = $from;\n";
$output .= "if (!is_array(\$_from) && !is_object(\$_from)) {\n";
$output .= "settype(\$_from, 'array');\n";
$output .= "}\n";
$output .= "\$_smarty_tpl->tpl_vars[$item] = new Smarty_Variable;\n";
$output .= "\$_smarty_tpl->tpl_vars[$item]->_loop = false;\n";
if ($key != null) {
$output .= "\$_smarty_tpl->tpl_vars[$key] = new Smarty_Variable;\n";
}
$output .= " \$_from = $from; if (!is_array(\$_from) && !is_object(\$_from)) { settype(\$_from, 'array');}\n";
if ($usesPropTotal) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->total= \$_smarty_tpl->_count(\$_from);\n";
$output .= "\$_smarty_tpl->tpl_vars[$item]->total= \$_smarty_tpl->_count(\$_from);\n";
}
if ($usesPropIteration) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->iteration=0;\n";
$output .= "\$_smarty_tpl->tpl_vars[$item]->iteration=0;\n";
}
if ($usesPropIndex) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->index=-1;\n";
$output .= "\$_smarty_tpl->tpl_vars[$item]->index=-1;\n";
}
if ($usesPropShow) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->show = (\$_smarty_tpl->tpl_vars[$item]->total > 0);\n";
if ($usesPropTotal) {
$output .= "\$_smarty_tpl->tpl_vars[$item]->show = (\$_smarty_tpl->tpl_vars[$item]->total > 0);\n";
} else {
$output .= "\$_smarty_tpl->tpl_vars[$item]->show = (\$_smarty_tpl->_count(\$_from) > 0);\n";
}
}
if ($has_name) {
$prop = array();
if ($usesSmartyTotal) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['total'] = \$_smarty_tpl->tpl_vars[$item]->total;\n";
$prop['total'] = "'total' => ";
$prop['total'] .= $usesSmartyShow ? '$total = ' : '';
$prop['total'] .= '$_smarty_tpl->_count($_from)';
}
if ($usesSmartyIteration) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['iteration']=0;\n";
$prop['iteration'] = "'iteration' => 0";
}
if ($usesSmartyIndex) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['index']=-1;\n";
$prop['index'] = "'index' => -1";
}
if ($usesSmartyShow) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['show']=(\$_smarty_tpl->tpl_vars[$item]->total > 0);\n";
$prop['show'] = "'show' => ";
if ($usesSmartyTotal) {
$prop['show'] .= "(\$total > 0)";
} else {
$prop['show'] .= "(\$_smarty_tpl->_count(\$_from) > 0)";
}
}
if ($useSmartyForeach) {
$_vars = 'array(' . join(', ', $prop) . ')';
$foreachVar = "'__foreach_{$name}'";
$output .= "\$_smarty_tpl->tpl_vars[$foreachVar] = new Smarty_Variable({$_vars});\n";
}
}
$output .= "foreach (\$_from as \$_smarty_tpl->tpl_vars[$item]->key => \$_smarty_tpl->tpl_vars[$item]->value) {\n\$_smarty_tpl->tpl_vars[$item]->_loop = true;\n";
if ($key != null) {
$output .= " \$_smarty_tpl->tpl_vars[$key]->value = \$_smarty_tpl->tpl_vars[$item]->key;\n";
$output .= "foreach (\$_from as {$keyTerm}\$_smarty_tpl->tpl_vars[$item]->value) {\n";
$output .= "\$_smarty_tpl->tpl_vars[$item]->_loop = true;\n";
if ($key != null && $usesPropKey) {
$output .= "\$_smarty_tpl->tpl_vars[$key]->value = \$_smarty_tpl->tpl_vars[$item]->key;\n";
}
if ($usesPropIteration) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->iteration++;\n";
$output .= "\$_smarty_tpl->tpl_vars[$item]->iteration++;\n";
}
if ($usesPropIndex) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->index++;\n";
$output .= "\$_smarty_tpl->tpl_vars[$item]->index++;\n";
}
if ($usesPropFirst) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->first = \$_smarty_tpl->tpl_vars[$item]->index === 0;\n";
if ($usesPropIndex) {
$output .= "\$_smarty_tpl->tpl_vars[$item]->first = \$_smarty_tpl->tpl_vars[$item]->index == 0;\n";
} else {
$output .= "\$_smarty_tpl->tpl_vars[$item]->first = \$_smarty_tpl->tpl_vars[$item]->iteration == 1;\n";
}
}
if ($usesPropLast) {
$output .= " \$_smarty_tpl->tpl_vars[$item]->last = \$_smarty_tpl->tpl_vars[$item]->iteration === \$_smarty_tpl->tpl_vars[$item]->total;\n";
if ($usesPropIndex) {
$output .= "\$_smarty_tpl->tpl_vars[$item]->last = \$_smarty_tpl->tpl_vars[$item]->index + 1 == \$_smarty_tpl->tpl_vars[$item]->total;\n";
} else {
$output .= "\$_smarty_tpl->tpl_vars[$item]->last = \$_smarty_tpl->tpl_vars[$item]->iteration == \$_smarty_tpl->tpl_vars[$item]->total;\n";
}
}
if ($has_name) {
if ($usesSmartyFirst) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['first'] = \$_smarty_tpl->tpl_vars[$item]->first;\n";
}
if ($usesSmartyIteration) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['iteration']++;\n";
$output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['iteration']++;\n";
}
if ($usesSmartyIndex) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['index']++;\n";
$output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['index']++;\n";
}
if ($usesSmartyFirst) {
if ($usesSmartyIndex) {
$output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['first'] = \$_smarty_tpl->tpl_vars[$foreachVar]->value['index'] == 0;\n";
} else {
$output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['first'] = \$_smarty_tpl->tpl_vars[$foreachVar]->value['iteration'] == 1;\n";
}
}
if ($usesSmartyLast) {
$output .= " \$_smarty_tpl->tpl_vars['smarty']->value['foreach'][$name]['last'] = \$_smarty_tpl->tpl_vars[$item]->last;\n";
if ($usesSmartyIndex) {
$output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['last'] = \$_smarty_tpl->tpl_vars[$foreachVar]->value['index'] + 1 == \$_smarty_tpl->tpl_vars[$foreachVar]->value['total'];\n";
} else {
$output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['last'] = \$_smarty_tpl->tpl_vars[$foreachVar]->value['iteration'] == \$_smarty_tpl->tpl_vars[$foreachVar]->value['total'];\n";
}
}
}
$itemName = trim($item,"'\"");
$output .= "\$foreach_{$itemName}_Sav = \$_smarty_tpl->tpl_vars[$item];\n";
$output .= "?>";
return $output;
@ -189,10 +238,14 @@ class Smarty_Internal_Compile_Foreachelse extends Smarty_Internal_CompileBase
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
list($openTag, $nocache, $item, $key) = $this->closeTag($compiler, array('foreach'));
$this->openTag($compiler, 'foreachelse', array('foreachelse', $nocache, $item, $key));
return "<?php }\nif (!\$_smarty_tpl->tpl_vars[$item]->_loop) {\n?>";
list($openTag, $nocache, $item, $key, $foo) = $this->closeTag($compiler, array('foreach'));
$this->openTag($compiler, 'foreachelse', array('foreachelse', $nocache, $item, $key, false));
$itemName = trim($item,"'\"");
$output = "<?php\n";
$output .= "\$_smarty_tpl->tpl_vars[$item] = \$foreach_{$itemName}_Sav;\n";
$output .= "}\n";
$output .= "if (!\$_smarty_tpl->tpl_vars[$item]->_loop) {\n?>";
return $output;
}
}
@ -222,8 +275,14 @@ class Smarty_Internal_Compile_Foreachclose extends Smarty_Internal_CompileBase
$compiler->tag_nocache = true;
}
list($openTag, $compiler->nocache, $item, $key) = $this->closeTag($compiler, array('foreach', 'foreachelse'));
list($openTag, $compiler->nocache, $item, $key, $restore) = $this->closeTag($compiler, array('foreach', 'foreachelse'));
$itemName = trim($item,"'\"");
$output = "<?php\n";
if ($restore) {
$output .= "\$_smarty_tpl->tpl_vars[$item] = \$foreach_{$itemName}_Sav;\n";
}
$output .= "}\n?>";
return "<?php } ?>";
return $output;
}
}

View File

@ -16,6 +16,7 @@
*/
class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase
{
/**
* Attribute definition: Overwrites base class.
*
@ -23,6 +24,7 @@ class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase
*/
public $required_attributes = array('name');
/**
* Attribute definition: Overwrites base class.
*
@ -30,6 +32,7 @@ class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase
* @see Smarty_Internal_CompileBase
*/
public $shorttag_order = array('name');
/**
* Attribute definition: Overwrites base class.
*
@ -56,39 +59,17 @@ class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase
$compiler->trigger_template_error('nocache option not allowed', $compiler->lex->taglineno);
}
unset($_attr['nocache']);
$save = array($_attr, $compiler->parser->current_buffer,
$compiler->template->has_nocache_code, $compiler->template->required_plugins);
$this->openTag($compiler, 'function', $save);
$_name = trim($_attr['name'], "'\"");
unset($_attr['name']);
$compiler->parent_compiler->templateProperties['tpl_function'][$_name] = array();
$save = array($_attr, $compiler->parser->current_buffer, $compiler->template->has_nocache_code, $compiler->template->required_plugins, $compiler->template->caching);
$this->openTag($compiler, 'function', $save);
// set flag that we are compiling a template function
$compiler->compiles_template_function = true;
$compiler->template->properties['function'][$_name]['parameter'] = array();
/** @var Smarty_Internal_Template $_smarty_tpl
* used in evaluated code
*/
$_smarty_tpl = $compiler->template;
foreach ($_attr as $_key => $_data) {
eval ('$tmp=' . $_data . ';');
$compiler->template->properties['function'][$_name]['parameter'][$_key] = $tmp;
}
$compiler->smarty->template_functions[$_name]['parameter'] = $compiler->template->properties['function'][$_name]['parameter'];
if ($compiler->template->caching) {
$output = '';
} else {
$output = "<?php if (!function_exists('smarty_template_function_{$_name}')) {
function smarty_template_function_{$_name}(\$_smarty_tpl,\$params) {
\$saved_tpl_vars = \$_smarty_tpl->tpl_vars;
foreach (\$_smarty_tpl->smarty->template_functions['{$_name}']['parameter'] as \$key => \$value) {\$_smarty_tpl->tpl_vars[\$key] = new Smarty_variable(\$value);};
foreach (\$params as \$key => \$value) {\$_smarty_tpl->tpl_vars[\$key] = new Smarty_variable(\$value);}?>";
}
// Init temporary context
$compiler->template->required_plugins = array('compiled' => array(), 'nocache' => array());
$compiler->parser->current_buffer = new _smarty_template_buffer($compiler->parser);
$compiler->parser->current_buffer->append_subtree(new _smarty_tag($compiler->parser, $output));
$compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template($compiler->parser);
$compiler->template->has_nocache_code = false;
$compiler->has_code = false;
$compiler->template->properties['function'][$_name]['compiled'] = '';
$compiler->template->caching = true;
return true;
}
}
@ -101,62 +82,149 @@ class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase
*/
class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
{
/**
* Compiler object
*
* @var object
*/
private $compiler = null;
/**
* Compiles code for the {/function} tag
*
* @param array $args array with attributes from parser
* @param object $compiler compiler object
* @param array $parameter array with compilation parameter
* @param array $args array with attributes from parser
* @param object|\Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @return boolean true
* @return bool true
*/
public function compile($args, $compiler, $parameter)
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{
$_attr = $this->getAttributes($compiler, $args);
$this->compiler = $compiler;
$saved_data = $this->closeTag($compiler, array('function'));
$_name = trim($saved_data[0]['name'], "'\"");
// build plugin include code
$plugins_string = '';
if (!empty($compiler->template->required_plugins['compiled'])) {
$plugins_string = '<?php ';
foreach ($compiler->template->required_plugins['compiled'] as $tmp) {
foreach ($tmp as $data) {
$plugins_string .= "if (!is_callable('{$data['function']}')) include '{$data['file']}';\n";
}
}
$plugins_string .= '?>';
}
if (!empty($compiler->template->required_plugins['nocache'])) {
$plugins_string .= "<?php echo '/*%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/<?php ";
foreach ($compiler->template->required_plugins['nocache'] as $tmp) {
foreach ($tmp as $data) {
$plugins_string .= "if (!is_callable(\'{$data['function']}\')) include \'{$data['file']}\';\n";
}
}
$plugins_string .= "?>/*/%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/';?>\n";
}
// if caching save template function for possible nocache call
if ($compiler->template->caching) {
$compiler->template->properties['function'][$_name]['compiled'] .= $plugins_string
. $compiler->parser->current_buffer->to_smarty_php();
$compiler->template->properties['function'][$_name]['nocache_hash'] = $compiler->template->properties['nocache_hash'];
$compiler->template->properties['function'][$_name]['has_nocache_code'] = $compiler->template->has_nocache_code;
$compiler->template->properties['function'][$_name]['called_functions'] = $compiler->called_functions;
$compiler->called_functions = array();
$compiler->smarty->template_functions[$_name] = $compiler->template->properties['function'][$_name];
$compiler->has_code = false;
$output = true;
} else {
$output = $plugins_string . $compiler->parser->current_buffer->to_smarty_php() . "<?php \$_smarty_tpl->tpl_vars = \$saved_tpl_vars;
foreach (Smarty::\$global_tpl_vars as \$key => \$value) if(!isset(\$_smarty_tpl->tpl_vars[\$key])) \$_smarty_tpl->tpl_vars[\$key] = \$value;}}?>\n";
}
$_attr = $saved_data[0];
$_name = trim($_attr['name'], "'\"");
// reset flag that we are compiling a template function
$compiler->compiles_template_function = false;
// restore old compiler status
$compiler->parser->current_buffer = $saved_data[1];
$compiler->template->has_nocache_code = $compiler->template->has_nocache_code | $saved_data[2];
$compiler->template->required_plugins = $saved_data[3];
$compiler->parent_compiler->templateProperties['tpl_function'][$_name]['called_functions'] = $compiler->called_functions;
$compiler->parent_compiler->templateProperties['tpl_function'][$_name]['compiled_filepath'] = $compiler->parent_compiler->template->compiled->filepath;
$compiler->parent_compiler->templateProperties['tpl_function'][$_name]['uid'] = $compiler->template->source->uid;
$compiler->called_functions = array();
$_parameter = $_attr;
unset($_parameter['name']);
// default parameter
$_paramsArray = array();
foreach ($_parameter as $_key => $_value) {
if (is_int($_key)) {
$_paramsArray[] = "$_key=>$_value";
} else {
$_paramsArray[] = "'$_key'=>$_value";
}
}
if (!empty($_paramsArray)) {
$_params = 'array(' . implode(",", $_paramsArray) . ')';
$_paramsCode = "\$params = array_merge($_params, \$params);\n";
} else {
$_paramsCode = '';
}
$_functionCode = $compiler->parser->current_buffer;
// setup buffer for template function code
$compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template($compiler->parser);
return $output;
$_funcName = "smarty_template_function_{$_name}_{$compiler->template->properties['nocache_hash']}";
$_funcNameCaching = $_funcName . '_nocache';
if ($compiler->template->has_nocache_code) {
$compiler->parent_compiler->templateProperties['tpl_function'][$_name]['call_name_caching'] = $_funcNameCaching;
$output = "<?php\n";
$output .= "/* {$_funcNameCaching} */\n";
$output .= "if (!function_exists('{$_funcNameCaching}')) {\n";
$output .= "function {$_funcNameCaching} (\$_smarty_tpl,\$params) {\n";
// build plugin include code
if (!empty($compiler->template->required_plugins['compiled'])) {
foreach ($compiler->template->required_plugins['compiled'] as $tmp) {
foreach ($tmp as $data) {
$output .= "if (!is_callable('{$data['function']}')) require_once '{$data['file']}';\n";
}
}
}
if (!empty($compiler->template->required_plugins['nocache'])) {
$output .= "echo '/*%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/<?php ";
foreach ($compiler->template->required_plugins['nocache'] as $tmp) {
foreach ($tmp as $data) {
$output .= "if (!is_callable(\'{$data['function']}\')) require_once \'{$data['file']}\';\n";
}
}
$output .= "?>/*/%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/';\n";
}
$output .= "ob_start();\n";
$output .= $_paramsCode;
$output .= "\$_smarty_tpl->properties['saved_tpl_vars'][] = \$_smarty_tpl->tpl_vars;\n";
$output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value);\n}";
$output .= "\$params = var_export(\$params, true);\n";
$output .= "echo \"/*%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/<?php ";
$output .= "\\\$saved_tpl_vars = \\\$_smarty_tpl->tpl_vars;\nforeach (\$params as \\\$key => \\\$value) {\n\\\$_smarty_tpl->tpl_vars[\\\$key] = new Smarty_Variable(\\\$value);\n}\n?>";
$output .= "/*/%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/\n\";?>";
$compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($compiler->parser, $output));
$compiler->parser->current_buffer->append_subtree($_functionCode);
$output = "<?php echo \"/*%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/<?php ";
$output .= "foreach (Smarty::\\\$global_tpl_vars as \\\$key => \\\$value){\n";
$output .= "if (\\\$_smarty_tpl->tpl_vars[\\\$key] === \\\$value) \\\$saved_tpl_vars[\\\$key] = \\\$value;\n}\n";
$output .= "\\\$_smarty_tpl->tpl_vars = \\\$saved_tpl_vars;?>\n";
$output .= "/*/%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/\";\n?>";
$output .= "<?php echo str_replace('{$compiler->template->properties['nocache_hash']}', \$_smarty_tpl->properties['nocache_hash'], ob_get_clean());\n";
$output .= "\$_smarty_tpl->tpl_vars = array_pop(\$_smarty_tpl->properties['saved_tpl_vars']);\n}\n}\n";
$output .= "/*/ {$_funcName}_nocache */\n\n";
$output .= "?>\n";
$compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($compiler->parser, $output));
$_functionCode = new Smarty_Internal_ParseTree_Tag($compiler->parser, preg_replace_callback("/((<\?php )?echo '\/\*%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%\*\/([\S\s]*?)\/\*\/%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%\*\/';(\?>\n)?)/", array($this, 'removeNocache'), $_functionCode->to_smarty_php()));
}
$compiler->parent_compiler->templateProperties['tpl_function'][$_name]['call_name'] = $_funcName;
$output = "<?php\n";
$output .= "/* {$_funcName} */\n";
$output .= "if (!function_exists('{$_funcName}')) {\n";
$output .= "function {$_funcName}(\$_smarty_tpl,\$params) {\n";
// build plugin include code
if (!empty($compiler->template->required_plugins['nocache'])) {
$compiler->template->required_plugins['compiled'] = array_merge($compiler->template->required_plugins['compiled'], $compiler->template->required_plugins['nocache']);
}
if (!empty($compiler->template->required_plugins['compiled'])) {
foreach ($compiler->template->required_plugins['compiled'] as $tmp) {
foreach ($tmp as $data) {
$output .= "if (!is_callable('{$data['function']}')) require_once '{$data['file']}';\n";
}
}
}
$output .= "\$saved_tpl_vars = \$_smarty_tpl->tpl_vars;\n";
$output .= $_paramsCode;
$output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value);\n}?>";
$compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($compiler->parser, $output));
$compiler->parser->current_buffer->append_subtree($_functionCode);
$output = "<?php foreach (Smarty::\$global_tpl_vars as \$key => \$value){\n";
$output .= "if (\$_smarty_tpl->tpl_vars[\$key] === \$value) \$saved_tpl_vars[\$key] = \$value;\n}\n";
$output .= "\$_smarty_tpl->tpl_vars = \$saved_tpl_vars;\n}\n}\n";
$output .= "/*/ {$_funcName} */\n\n";
$output .= "?>\n";
$compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($compiler->parser, $output));
$compiler->parent_compiler->templateFunctionCode .= $compiler->parser->current_buffer->to_smarty_php();
// restore old buffer
$compiler->parser->current_buffer = $saved_data[1];
// restore old status
$compiler->template->has_nocache_code = $saved_data[2];
$compiler->template->required_plugins = $saved_data[3];
$compiler->template->caching = $saved_data[4];
return true;
}
/**
* @param $match
*
* @return mixed
*/
function removeNocache($match)
{
$code = preg_replace("/((<\?php )?echo '\/\*%%SmartyNocache:{$this->compiler->template->properties['nocache_hash']}%%\*\/)|(\/\*\/%%SmartyNocache:{$this->compiler->template->properties['nocache_hash']}%%\*\/';(\?>\n)?)/", '', $match[0]);
$code = str_replace(array('\\\'', '\\\\\''), array('\'', '\\\''), $code);
return $code;
}
}

View File

@ -42,9 +42,14 @@ class Smarty_Internal_Compile_If extends Smarty_Internal_CompileBase
$_nocache = ',true';
// create nocache var to make it know for further compiling
if (is_array($parameter['if condition']['var'])) {
$compiler->template->tpl_vars[trim($parameter['if condition']['var']['var'], "'")] = new Smarty_variable(null, true);
$var = trim($parameter['if condition']['var']['var'], "'");
} else {
$compiler->template->tpl_vars[trim($parameter['if condition']['var'], "'")] = new Smarty_variable(null, true);
$var = trim($parameter['if condition']['var'], "'");
}
if (isset($compiler->template->tpl_vars[$var])) {
$compiler->template->tpl_vars[$var]->nocache = true;
} else {
$compiler->template->tpl_vars[$var] = new Smarty_Variable(null, true);
}
} else {
$_nocache = '';
@ -124,9 +129,14 @@ class Smarty_Internal_Compile_Elseif extends Smarty_Internal_CompileBase
$_nocache = ',true';
// create nocache var to make it know for further compiling
if (is_array($parameter['if condition']['var'])) {
$compiler->template->tpl_vars[trim($parameter['if condition']['var']['var'], "'")] = new Smarty_variable(null, true);
$var = trim($parameter['if condition']['var']['var'], "'");
} else {
$compiler->template->tpl_vars[trim($parameter['if condition']['var'], "'")] = new Smarty_variable(null, true);
$var = trim($parameter['if condition']['var'], "'");
}
if (isset($compiler->template->tpl_vars[$var])) {
$compiler->template->tpl_vars[$var]->nocache = true;
} else {
$compiler->template->tpl_vars[$var] = new Smarty_Variable(null, true);
}
} else {
$_nocache = '';
@ -155,22 +165,23 @@ class Smarty_Internal_Compile_Elseif extends Smarty_Internal_CompileBase
} else {
$tmp = '';
foreach ($compiler->prefix_code as $code) {
$tmp .= $code;
}
$tmp = $compiler->appendCode($tmp, $code);
}
$compiler->prefix_code = array();
$tmp = $compiler->appendCode("<?php } else {?>", $tmp);
$this->openTag($compiler, 'elseif', array($nesting + 1, $compiler->tag_nocache));
if ($condition_by_assign) {
if (is_array($parameter['if condition']['var'])) {
$_output = "<?php } else {?>{$tmp}<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value)) \$_smarty_tpl->createLocalArrayVariable(" . $parameter['if condition']['var']['var'] . "$_nocache);\n";
$_output = $compiler->appendCode($tmp, "<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value)) \$_smarty_tpl->createLocalArrayVariable(" . $parameter['if condition']['var']['var'] . "$_nocache);\n");
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" . $parameter['if condition']['var']['smarty_internal_index'] . " = " . $parameter['if condition']['value'] . ") {?>";
} else {
$_output = "<?php } else {?>{$tmp}<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "])) \$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "] = new Smarty_Variable(null{$_nocache});";
$_output = $compiler->appendCode($tmp, "<?php if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "])) \$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "] = new Smarty_Variable(null{$_nocache});");
$_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var'] . "]->value = " . $parameter['if condition']['value'] . ") {?>";
}
return $_output;
} else {
return "<?php } else {?>{$tmp}<?php if ({$parameter['if condition']}) {?>";
return $compiler->appendCode($tmp, "<?php if ({$parameter['if condition']}) {?>");
}
}
}

View File

@ -52,16 +52,18 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
/**
* Compiles code for the {include} tag
*
* @param array $args array with attributes from parser
* @param object $compiler compiler object
* @param array $parameter array with compilation parameter
* @param array $args array with attributes from parser
* @param Smarty_Internal_SmartyTemplateCompiler $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @throws SmartyCompilerException
* @return string compiled code
*/
public function compile($args, $compiler, $parameter)
public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $parameter)
{
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
// save possible attributes
$include_file = $_attr['file'];
@ -82,32 +84,73 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
}
}
// assume caching is off
$_caching = Smarty::CACHING_OFF;
if ($_attr['nocache'] === true) {
$compiler->tag_nocache = true;
}
$call_nocache = $compiler->tag_nocache || $compiler->nocache;
// caching was on and {include} is not in nocache mode
if ($compiler->template->caching && !$compiler->nocache && !$compiler->tag_nocache) {
$_caching = self::CACHING_NOCACHE_CODE;
}
// flag if included template code should be merged into caller
$merge_compiled_includes = ($compiler->smarty->merge_compiled_includes || ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) || $_attr['inline'] === true) && !$compiler->template->source->recompiled;
// set default when in nocache mode
// if ($compiler->template->caching && ($compiler->nocache || $compiler->tag_nocache || $compiler->forceNocache == 2)) {
if ($compiler->template->caching && ((!$compiler->inheritance && !$compiler->nocache && !$compiler->tag_nocache) || ($compiler->inheritance && ($compiler->nocache || $compiler->tag_nocache)))) {
$_caching = self::CACHING_NOCACHE_CODE;
if ($merge_compiled_includes && $_attr['inline'] !== true) {
// variable template name ?
if ($compiler->has_variable_string || !((substr_count($include_file, '"') == 2 || substr_count($include_file, "'") == 2)) || substr_count($include_file, '(') != 0 || substr_count($include_file, '$_smarty_tpl->') != 0) {
$merge_compiled_includes = false;
if ($compiler->template->caching) {
// must use individual cache file
//$_attr['caching'] = 1;
}
if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes && $_attr['inline'] !== true) {
$compiler->trigger_template_error(' variable template file names not allow within {block} tags');
}
}
// variable compile_id?
if (isset($_attr['compile_id'])) {
if (!((substr_count($_attr['compile_id'], '"') == 2 || substr_count($_attr['compile_id'], "'") == 2 || is_numeric($_attr['compile_id']))) || substr_count($_attr['compile_id'], '(') != 0 || substr_count($_attr['compile_id'], '$_smarty_tpl->') != 0) {
$merge_compiled_includes = false;
if ($compiler->template->caching) {
// must use individual cache file
//$_attr['caching'] = 1;
}
if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes && $_attr['inline'] !== true) {
$compiler->trigger_template_error(' variable compile_id not allow within {block} tags');
}
}
}
}
/*
* if the {include} tag provides individual parameter for caching
* it will not be included into the common cache file and treated like
* a nocache section
* if the {include} tag provides individual parameter for caching or compile_id
* the subtemplate must not be included into the common cache file and is treated like
* a call in nocache mode.
*
*/
if ($_attr['nocache'] !== true && $_attr['caching']) {
$_caching = $_new_caching = (int) $_attr['caching'];
$call_nocache = true;
} else {
$_new_caching = Smarty::CACHING_LIFETIME_CURRENT;
}
if (isset($_attr['cache_lifetime'])) {
$_cache_lifetime = $_attr['cache_lifetime'];
$compiler->tag_nocache = true;
$_caching = Smarty::CACHING_LIFETIME_CURRENT;
$call_nocache = true;
$_caching = $_new_caching;
} else {
$_cache_lifetime = 'null';
$_cache_lifetime = '$_smarty_tpl->cache_lifetime';
}
if (isset($_attr['cache_id'])) {
$_cache_id = $_attr['cache_id'];
$compiler->tag_nocache = true;
$_caching = Smarty::CACHING_LIFETIME_CURRENT;
$call_nocache = true;
$_caching = $_new_caching;
} else {
$_cache_id = '$_smarty_tpl->cache_id';
}
@ -116,85 +159,47 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
} else {
$_compile_id = '$_smarty_tpl->compile_id';
}
if ($_attr['caching'] === true) {
$_caching = Smarty::CACHING_LIFETIME_CURRENT;
}
if ($_attr['nocache'] === true) {
$compiler->tag_nocache = true;
if ($merge_compiled_includes) {
$_caching = self::CACHING_NOCACHE_CODE;
} else {
$_caching = Smarty::CACHING_OFF;
}
// if subtemplate will be called in nocache mode do not merge
if ($compiler->template->caching && $call_nocache) {
$merge_compiled_includes = false;
}
$has_compiled_template = false;
if ($merge_compiled_includes && $_attr['inline'] !== true) {
// variable template name ?
if ($compiler->has_variable_string || !((substr_count($include_file, '"') == 2 || substr_count($include_file, "'") == 2))
|| substr_count($include_file, '(') != 0 || substr_count($include_file, '$_smarty_tpl->') != 0
) {
$merge_compiled_includes = false;
if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) {
$compiler->trigger_template_error(' variable template file names not allow within {block} tags');
}
}
// variable compile_id?
if (isset($_attr['compile_id'])) {
if (!((substr_count($_attr['compile_id'], '"') == 2 || substr_count($_attr['compile_id'], "'") == 2))
|| substr_count($_attr['compile_id'], '(') != 0 || substr_count($_attr['compile_id'], '$_smarty_tpl->') != 0
) {
$merge_compiled_includes = false;
if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) {
$compiler->trigger_template_error(' variable compile_id not allow within {block} tags');
}
}
}
}
if ($merge_compiled_includes) {
if ($compiler->template->caching && ($compiler->tag_nocache || $compiler->nocache) && $_caching != self::CACHING_NOCACHE_CODE) {
$merge_compiled_includes = false;
// $merge_compiled_includes = false;
if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) {
$compiler->trigger_template_error(' invalid caching mode of subtemplate within {block} tags');
}
}
}
if ($merge_compiled_includes) {
// we must observe different compile_id
$uid = sha1($_compile_id);
$c_id = isset($_attr['compile_id']) ? $_attr['compile_id'] : $compiler->template->compile_id;
// we must observe different compile_id and caching
$uid = sha1($c_id . ($_caching ? '--caching' : '--nocaching'));
$tpl_name = null;
$nocache = false;
/** @var Smarty_Internal_Template $_smarty_tpl
* used in evaluated code
*/
$_smarty_tpl = $compiler->template;
eval("\$tpl_name = $include_file;");
if (!isset($compiler->smarty->merged_templates_func[$tpl_name][$uid])) {
$tpl = new $compiler->smarty->template_class ($tpl_name, $compiler->smarty, $compiler->template, $compiler->template->cache_id, $compiler->template->compile_id);
if (!isset($compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid])) {
$compiler->smarty->allow_ambiguous_resources = true;
$tpl = new $compiler->smarty->template_class ($tpl_name, $compiler->smarty, $compiler->template, $compiler->template->cache_id, $c_id, $_caching);
// save unique function name
$compiler->smarty->merged_templates_func[$tpl_name][$uid]['func'] = $tpl->properties['unifunc'] = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
// use current nocache hash for inlined code
$compiler->smarty->merged_templates_func[$tpl_name][$uid]['nocache_hash'] = $tpl->properties['nocache_hash'] = $compiler->template->properties['nocache_hash'];
if ($compiler->template->caching && $_caching == self::CACHING_NOCACHE_CODE) {
// all code must be nocache
$nocache = true;
}
$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func'] = $tpl->properties['unifunc'] = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
if ($compiler->inheritance) {
$tpl->compiler->inheritance = true;
}
// make sure whole chain gets compiled
$tpl->mustCompile = true;
if (!($tpl->source->uncompiled) && $tpl->source->exists) {
$tpl->compiler->suppressTemplatePropertyHeader = true;
$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['nocache_hash'] = $tpl->properties['nocache_hash'] = str_replace(array('.', ','), '_', uniqid(rand(), true));
// get compiled code
$compiled_code = $tpl->compiler->compileTemplate($tpl, $nocache);
// release compiler object to free memory
$compiled_code = Smarty_Internal_Extension_CodeFrame::createFunctionFrame($tpl, $tpl->compiler->compileTemplate($tpl, null, $compiler->parent_compiler));
unset($tpl->compiler);
// merge compiled code for {function} tags
$compiler->template->properties['function'] = array_merge($compiler->template->properties['function'], $tpl->properties['function']);
// merge filedependency
$tpl->properties['file_dependency'][$tpl->source->uid] = array($tpl->source->filepath, $tpl->source->timestamp, $tpl->source->type);
$compiler->template->properties['file_dependency'] = array_merge($compiler->template->properties['file_dependency'], $tpl->properties['file_dependency']);
// remove header code
$compiled_code = preg_replace("/(<\?php \/\*%%SmartyHeaderCode:{$tpl->properties['nocache_hash']}%%\*\/(.+?)\/\*\/%%SmartyHeaderCode%%\*\/\?>\n)/s", '', $compiled_code);
if ($tpl->has_nocache_code) {
@ -202,8 +207,22 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
$compiled_code = str_replace("{$tpl->properties['nocache_hash']}", $compiler->template->properties['nocache_hash'], $compiled_code);
$compiler->template->has_nocache_code = true;
}
$compiler->merged_templates[$tpl->properties['unifunc']] = $compiled_code;
$compiler->parent_compiler->mergedSubTemplatesCode[$tpl->properties['unifunc']] = $compiled_code;
$has_compiled_template = true;
if (!empty($tpl->required_plugins['compiled'])) {
foreach ($tpl->required_plugins['compiled'] as $name => $callBack) {
if (!isset($compiler->template->required_plugins['compiled'][$name])) {
$compiler->template->required_plugins['compiled'][$name] = $callBack;
}
}
}
if (!empty($tpl->required_plugins['nocache'])) {
foreach ($tpl->required_plugins['nocache'] as $name => $callBack) {
if (!isset($compiler->template->required_plugins['nocache'][$name])) {
$compiler->template->required_plugins['nocache'][$name] = $callBack;
}
}
}
unset ($tpl);
}
} else {
@ -213,13 +232,14 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
// delete {include} standard attributes
unset($_attr['file'], $_attr['assign'], $_attr['cache_id'], $_attr['compile_id'], $_attr['cache_lifetime'], $_attr['nocache'], $_attr['caching'], $_attr['scope'], $_attr['inline']);
// remaining attributes must be assigned as smarty variable
$_vars_nc = '';
if (!empty($_attr)) {
if ($_parent_scope == Smarty::SCOPE_LOCAL) {
$_pairs = array();
// create variables
$nccode = '';
foreach ($_attr as $key => $value) {
$_pairs[] = "'$key'=>$value";
$nccode .= "\$_smarty_tpl->tpl_vars['$key'] = new Smarty_variable($value);\n";
$_vars_nc .= "\$_smarty_tpl->tpl_vars['$key'] = new Smarty_Variable($value);\n";
}
$_vars = 'array(' . join(',', $_pairs) . ')';
} else {
@ -228,38 +248,51 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
} else {
$_vars = 'array()';
}
if ($has_compiled_template) {
$update_compile_id = $compiler->template->caching && !$compiler->tag_nocache && !$compiler->nocache && $_compile_id != '$_smarty_tpl->compile_id';
if ($has_compiled_template && !$call_nocache) {
// if ($has_compiled_template && !$compiler->tag_nocache && !$compiler->nocache) {
// never call inline templates in nocache mode
$compiler->suppressNocacheProcessing = true;
$_hash = $compiler->smarty->merged_templates_func[$tpl_name][$uid]['nocache_hash'];
//$compiler->suppressNocacheProcessing = true;
$_hash = $compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['nocache_hash'];
$_output = "<?php /* Call merged included template \"" . $tpl_name . "\" */\n";
$_output .= "\$_tpl_stack[] = \$_smarty_tpl;\n";
if (!empty($nccode) && $_caching == 9999 && $_smarty_tpl->caching) {
$compiler->suppressNocacheProcessing = false;
$_output .= substr($compiler->processNocacheCode('<?php ' .$nccode . "?>\n", true), 6, -3);
$compiler->suppressNocacheProcessing = true;
if ($update_compile_id) {
$_output .= $compiler->makeNocacheCode("\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n");
}
if (!empty($_vars_nc) && $_caching == 9999 && $_smarty_tpl->caching) {
//$compiler->suppressNocacheProcessing = false;
$_output .= substr($compiler->processNocacheCode('<?php ' . $_vars_nc . "?>\n", true), 6, - 3);
//$compiler->suppressNocacheProcessing = true;
}
$_output .= " \$_smarty_tpl = \$_smarty_tpl->setupInlineSubTemplate($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope, '$_hash');\n";
if (isset($_assign)) {
$_output .= 'ob_start(); ';
$_output .= " \$_smarty_tpl->tpl_vars[$_assign] = new Smarty_Variable(\$_smarty_tpl->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, '{$_hash}', '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func']}'));\n";
} else {
$_output .= "echo \$_smarty_tpl->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, '{$_hash}', '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func']}');\n";
}
$_output .= $compiler->smarty->merged_templates_func[$tpl_name][$uid]['func'] . "(\$_smarty_tpl);\n";
$_output .= "\$_smarty_tpl = array_pop(\$_tpl_stack); ";
if (isset($_assign)) {
$_output .= " \$_smarty_tpl->tpl_vars[$_assign] = new Smarty_variable(ob_get_clean());";
if ($update_compile_id) {
$_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n");
}
$_output .= "\n/* End of included template \"" . $tpl_name . "\" */?>";
$_output .= "/* End of included template \"" . $tpl_name . "\" */?>\n";
return $_output;
}
if ($call_nocache) {
$compiler->tag_nocache = true;
}
$_output = "<?php ";
if ($update_compile_id) {
$_output .= "\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n";
}
// was there an assign attribute
if (isset($_assign)) {
$_output = "<?php \$_smarty_tpl->tpl_vars[$_assign] = new Smarty_variable(\$_smarty_tpl->getSubTemplate ($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope));?>\n";;
$_output .= "\$_smarty_tpl->tpl_vars[$_assign] = new Smarty_Variable(\$_smarty_tpl->getSubTemplate ($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope));\n";
} else {
$_output = "<?php echo \$_smarty_tpl->getSubTemplate ($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope);?>\n";
$_output .= "echo \$_smarty_tpl->getSubTemplate ($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope);\n";
}
if ($update_compile_id) {
$_output .= "\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n";
}
$_output .= "?>\n";
return $_output;
}
}

View File

@ -51,8 +51,11 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
{
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
// never compile as nocache code
$compiler->suppressNocacheProcessing = true;
$nocacheParam = $compiler->template->caching && ($compiler->tag_nocache || $compiler->nocache);
if (!$nocacheParam) {
// do not compile as nocache code
$compiler->suppressNocacheProcessing = true;
}
$compiler->tag_nocache = true;
$_smarty_tpl = $compiler->template;
$_name = null;
@ -65,7 +68,12 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
// output will be stored in a smarty variable instead of being displayed
$_assign = $_attr['assign'];
// create variable to make sure that the compiler knows about its nocache status
$compiler->template->tpl_vars[trim($_attr['assign'], "'")] = new Smarty_Variable(null, true);
$var = trim($_attr['assign'], "'");
if (isset($compiler->template->tpl_vars[$var])) {
$compiler->template->tpl_vars[$var]->nocache = true;
} else {
$compiler->template->tpl_vars[$var] = new Smarty_Variable(null, true);
}
}
if (isset($_attr['script'])) {
// script which must be included
@ -116,19 +124,19 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
// convert attributes into parameter array string
$_paramsArray = array();
foreach ($_attr as $_key => $_value) {
$_paramsArray[] = "'$_key' => $_value";
$_paramsArray[] = "'$_key' => $_value";
}
$_params = 'array(' . implode(", ", $_paramsArray) . ')';
// call insert
if (isset($_assign)) {
if ($_smarty_tpl->caching) {
if ($_smarty_tpl->caching && !$nocacheParam) {
$_output .= "echo Smarty_Internal_Nocache_Insert::compile ('{$_function}',{$_params}, \$_smarty_tpl, '{$_filepath}',{$_assign});?>";
} else {
$_output .= "\$_smarty_tpl->assign({$_assign} , {$_function} ({$_params},\$_smarty_tpl), true);?>";
}
} else {
$compiler->has_output = true;
if ($_smarty_tpl->caching) {
if ($_smarty_tpl->caching && !$nocacheParam) {
$_output .= "echo Smarty_Internal_Nocache_Insert::compile ('{$_function}',{$_params}, \$_smarty_tpl, '{$_filepath}');?>";
} else {
$_output .= "echo {$_function}({$_params},\$_smarty_tpl);?>";

View File

@ -16,6 +16,13 @@
*/
class Smarty_Internal_Compile_Nocache extends Smarty_Internal_CompileBase
{
/**
* Array of names of valid option flags
*
* @var array
*/
public $option_flags = array();
/**
* Compiles code for the {nocache} tag
* This tag does not generate compiled output. It only sets a compiler flag.
@ -28,9 +35,7 @@ class Smarty_Internal_Compile_Nocache extends Smarty_Internal_CompileBase
public function compile($args, $compiler)
{
$_attr = $this->getAttributes($compiler, $args);
if ($_attr['nocache'] === true) {
$compiler->trigger_template_error('nocache option not allowed', $compiler->lex->taglineno);
}
$this->openTag($compiler, 'nocache', array($compiler->nocache));
// enter nocache mode
$compiler->nocache = true;
// this tag does not return compiled code
@ -61,7 +66,7 @@ class Smarty_Internal_Compile_Nocacheclose extends Smarty_Internal_CompileBase
{
$_attr = $this->getAttributes($compiler, $args);
// leave nocache mode
$compiler->nocache = false;
list($compiler->nocache) = $this->closeTag($compiler, array('nocache'));
// this tag does not return compiled code
$compiler->has_code = false;

View File

@ -0,0 +1,197 @@
<?php
/**
* Smarty Internal Plugin Compile PHP Expression
* Compiles any tag which will output an expression or variable
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
/**
* Smarty Internal Plugin Compile PHP Expression Class
*
* @package Smarty
* @subpackage Compiler
*/
class Smarty_Internal_Compile_Private_Php extends Smarty_Internal_CompileBase
{
/**
* Attribute definition: Overwrites base class.
*
* @var array
* @see Smarty_Internal_CompileBase
*/
public $required_attributes = array('code', 'type');
/**
* Compiles code for generating output from any expression
*
* @param array $args array with attributes from parser
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @return string
* @throws \SmartyException
*/
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
{
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
$compiler->has_code = false;
if ($_attr['type'] == 'xml') {
$compiler->tag_nocache = true;
$save = $compiler->template->has_nocache_code;
$output = addcslashes($_attr['code'], "'\\");
$compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($compiler->parser, $compiler->processNocacheCode("<?php echo '" . $output . "';?>", $compiler, true)));
$compiler->template->has_nocache_code = $save;
return '';
}
if ($_attr['type'] != 'tag') {
if ($compiler->php_handling == Smarty::PHP_REMOVE) {
return '';
} elseif ($compiler->php_handling == Smarty::PHP_QUOTE) {
$output = preg_replace_callback('#(<\?(?:php|=)?)|(<%)|(<script\s+language\s*=\s*["\']?\s*php\s*["\']?\s*>)|(\?>)|(%>)|(<\/script>)#i', array($this,
'quote'), $_attr['code']);
$compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Text($compiler->parser, $output));
return '';
} elseif ($compiler->php_handling == Smarty::PHP_PASSTHRU || $_attr['type'] == 'unmatched') {
$compiler->tag_nocache = true;
$save = $compiler->template->has_nocache_code;
$output = addcslashes($_attr['code'], "'\\");
$compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($compiler->parser, $compiler->processNocacheCode("<?php echo '" . $output . "';?>", $compiler, true)));
$compiler->template->has_nocache_code = $save;
return '';
} elseif ($compiler->php_handling == Smarty::PHP_ALLOW) {
if (!($compiler->smarty instanceof SmartyBC)) {
$compiler->trigger_template_error('$smarty->php_handling PHP_ALLOW not allowed. Use SmartyBC to enable it', $compiler->lex->taglineno);
}
$compiler->has_code = true;
return $_attr['code'];
} else {
$compiler->trigger_template_error('Illegal $smarty->php_handling value', $compiler->lex->taglineno);
}
} else {
$compiler->has_code = true;
if (!($compiler->smarty instanceof SmartyBC)) {
$compiler->trigger_template_error('{php}[/php} tags not allowed. Use SmartyBC to enable them', $compiler->lex->taglineno);
}
$ldel = preg_quote($compiler->smarty->left_delimiter, '#');
$rdel = preg_quote($compiler->smarty->right_delimiter, '#');
preg_match("#^({$ldel}php\\s*)((.)*?)({$rdel})#", $_attr['code'], $match);
if (!empty($match[2])) {
if ('nocache' == trim($match[2])) {
$compiler->tag_nocache = true;
} else {
$compiler->trigger_template_error("illegal value of option flag \"{$match[2]}\"", $compiler->lex->taglineno);
}
}
return preg_replace(array("#^{$ldel}\\s*php\\s*(.)*?{$rdel}#",
"#{$ldel}\\s*/\\s*php\\s*{$rdel}$#"), array('<?php ', '?>'), $_attr['code']);
}
}
/**
* Lexer code for PHP tags
*
* This code has been moved from lexer here fo easier debugging and maintenance
*
* @param $lex
*/
public function parsePhp($lex)
{
$lex->token = Smarty_Internal_Templateparser::TP_PHP;
$close = 0;
$lex->taglineno = $lex->line;
$closeTag = '?>';
if (strpos($lex->value, '<?xml') === 0) {
$lex->is_xml = true;
$lex->token = Smarty_Internal_Templateparser::TP_NOCACHE;
return;
} elseif (strpos($lex->value, '<?') === 0) {
$lex->phpType = 'php';
} elseif (strpos($lex->value, '<%') === 0) {
$lex->phpType = 'asp';
$closeTag = '%>';
} elseif (strpos($lex->value, '%>') === 0) {
$lex->phpType = 'unmatched';
} elseif (strpos($lex->value, '?>') === 0) {
if ($lex->is_xml) {
$lex->is_xml = false;
$lex->token = Smarty_Internal_Templateparser::TP_NOCACHE;
return;
}
$lex->phpType = 'unmatched';
} elseif (strpos($lex->value, '<s') === 0) {
$lex->phpType = 'script';
$closeTag = '</script>';
} elseif (strpos($lex->value, $lex->smarty->left_delimiter) === 0) {
if ($lex->isAutoLiteral()) {
$lex->token = Smarty_Internal_Templateparser::TP_TEXT;
return;
}
$closeTag = "{$lex->smarty->left_delimiter}/php{$lex->smarty->right_delimiter}";
if ($lex->value == $closeTag) {
$lex->compiler->trigger_template_error("unexpected closing tag '{$closeTag}'");
}
$lex->phpType = 'tag';
}
if ($lex->phpType == 'unmatched') {
return;
}
if (($lex->phpType == 'php' || $lex->phpType == 'asp') && ($lex->compiler->php_handling == Smarty::PHP_PASSTHRU || $lex->compiler->php_handling == Smarty::PHP_QUOTE)) {
return;
}
$start = $lex->counter + strlen($lex->value);
$body = true;
if (preg_match('~' . preg_quote($closeTag, '~') . '~i', $lex->data, $match, PREG_OFFSET_CAPTURE, $start)) {
$close = $match[0][1];
} else {
$lex->compiler->trigger_template_error("missing closing tag '{$closeTag}'");
}
while ($body) {
if (preg_match('~([/][*])|([/][/][^\n]*)|(\'[^\'\\\\]*(?:\\.[^\'\\\\]*)*\')|("[^"\\\\]*(?:\\.[^"\\\\]*)*")~', $lex->data, $match, PREG_OFFSET_CAPTURE, $start)) {
$value = $match[0][0];
$from = $pos = $match[0][1];
if ($pos > $close) {
$body = false;
} else {
$start = $pos + strlen($value);
$phpCommentStart = $value == '/*';
if ($phpCommentStart) {
$phpCommentEnd = preg_match('~([*][/])~', $lex->data, $match, PREG_OFFSET_CAPTURE, $start);
if ($phpCommentEnd) {
$pos2 = $match[0][1];
$start = $pos2 + strlen($match[0][0]);
}
}
while ($close > $pos && $close < $start) {
if (preg_match('~' . preg_quote($closeTag, '~') . '~i', $lex->data, $match, PREG_OFFSET_CAPTURE, $from)) {
$close = $match[0][1];
$from = $close + strlen($match[0][0]);
} else {
$lex->compiler->trigger_template_error("missing closing tag '{$closeTag}'");
}
}
if ($phpCommentStart && (!$phpCommentEnd || $pos2 > $close)) {
$lex->taglineno = $lex->line + substr_count(substr($lex->data, $lex->counter, $start), "\n");
$lex->compiler->trigger_template_error("missing PHP comment closing tag '*/'");
}
}
} else {
$body = false;
}
}
$lex->value = substr($lex->data, $lex->counter, $close + strlen($closeTag) - $lex->counter);
}
/*
* Call back function for $php_handling = PHP_QUOTE
*
*/
private function quote($match)
{
return htmlspecialchars($match[0], ENT_QUOTES);
}
}

View File

@ -30,85 +30,91 @@ class Smarty_Internal_Compile_Private_Special_Variable extends Smarty_Internal_C
$_index = preg_split("/\]\[/", substr($parameter, 1, strlen($parameter) - 2));
$compiled_ref = ' ';
$variable = trim($_index[0], "'");
switch ($variable) {
case 'foreach':
return "\$_smarty_tpl->getVariable('smarty')->value$parameter";
case 'section':
return "\$_smarty_tpl->getVariable('smarty')->value$parameter";
case 'capture':
return "Smarty::\$_smarty_vars$parameter";
case 'now':
return 'time()';
case 'cookies':
if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_super_globals) {
$compiler->trigger_template_error("(secure mode) super globals not permitted");
if (!isset($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedSpecialSmartyVar($variable, $compiler)) {
switch ($variable) {
case 'foreach':
$name = trim($_index[1], "'");
$foreachVar = "'__foreach_{$name}'";
return "(isset(\$_smarty_tpl->tpl_vars[$foreachVar]->value[{$_index[2]}]) ? \$_smarty_tpl->tpl_vars[$foreachVar]->value[{$_index[2]}] : null)";
case 'section':
return "\$_smarty_tpl->getVariable('smarty')->value$parameter";
case 'capture':
return "Smarty::\$_smarty_vars$parameter";
case 'now':
return 'time()';
case 'cookies':
if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_super_globals) {
$compiler->trigger_template_error("(secure mode) super globals not permitted");
break;
}
$compiled_ref = '$_COOKIE';
break;
}
$compiled_ref = '$_COOKIE';
break;
case 'get':
case 'post':
case 'env':
case 'server':
case 'session':
case 'request':
if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_super_globals) {
$compiler->trigger_template_error("(secure mode) super globals not permitted");
case 'get':
case 'post':
case 'env':
case 'server':
case 'session':
case 'request':
if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_super_globals) {
$compiler->trigger_template_error("(secure mode) super globals not permitted");
break;
}
$compiled_ref = '$_' . strtoupper($variable);
break;
}
$compiled_ref = '$_' . strtoupper($variable);
break;
case 'template':
return 'basename($_smarty_tpl->source->filepath)';
case 'template':
return 'basename($_smarty_tpl->source->filepath)';
case 'template_object':
return '$_smarty_tpl';
case 'template_object':
return '$_smarty_tpl';
case 'current_dir':
return 'dirname($_smarty_tpl->source->filepath)';
case 'current_dir':
return 'dirname($_smarty_tpl->source->filepath)';
case 'version':
$_version = Smarty::SMARTY_VERSION;
case 'version':
$_version = Smarty::SMARTY_VERSION;
return "'$_version'";
return "'$_version'";
case 'const':
if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_constants) {
$compiler->trigger_template_error("(secure mode) constants not permitted");
case 'const':
if (isset($compiler->smarty->security_policy) && !$compiler->smarty->security_policy->allow_constants) {
$compiler->trigger_template_error("(secure mode) constants not permitted");
break;
}
if (strpos($_index[1], '$') === false && strpos($_index[1], '\'') === false ) {
return "@constant('{$_index[1]}')";
} else {
return "@constant({$_index[1]})";
}
case 'config':
if (isset($_index[2])) {
return "(is_array(\$tmp = \$_smarty_tpl->getConfigVariable($_index[1])) ? \$tmp[$_index[2]] : null)";
} else {
return "\$_smarty_tpl->getConfigVariable($_index[1])";
}
case 'ldelim':
$_ldelim = $compiler->smarty->left_delimiter;
return "'$_ldelim'";
case 'rdelim':
$_rdelim = $compiler->smarty->right_delimiter;
return "'$_rdelim'";
default:
$compiler->trigger_template_error('$smarty.' . trim($_index[0], "'") . ' is invalid');
break;
}
if (isset($_index[1])) {
array_shift($_index);
foreach ($_index as $_ind) {
$compiled_ref = $compiled_ref . "[$_ind]";
}
return "@constant({$_index[1]})";
case 'config':
if (isset($_index[2])) {
return "(is_array(\$tmp = \$_smarty_tpl->getConfigVariable($_index[1])) ? \$tmp[$_index[2]] : null)";
} else {
return "\$_smarty_tpl->getConfigVariable($_index[1])";
}
case 'ldelim':
$_ldelim = $compiler->smarty->left_delimiter;
return "'$_ldelim'";
case 'rdelim':
$_rdelim = $compiler->smarty->right_delimiter;
return "'$_rdelim'";
default:
$compiler->trigger_template_error('$smarty.' . trim($_index[0], "'") . ' is invalid');
break;
}
if (isset($_index[1])) {
array_shift($_index);
foreach ($_index as $_ind) {
$compiled_ref = $compiled_ref . "[$_ind]";
}
}
return $compiled_ref;
}
}

View File

@ -42,9 +42,14 @@ class Smarty_Internal_Compile_While extends Smarty_Internal_CompileBase
$_nocache = ',true';
// create nocache var to make it know for further compiling
if (is_array($parameter['if condition']['var'])) {
$compiler->template->tpl_vars[trim($parameter['if condition']['var']['var'], "'")] = new Smarty_variable(null, true);
$var = trim($parameter['if condition']['var']['var'], "'");
} else {
$compiler->template->tpl_vars[trim($parameter['if condition']['var'], "'")] = new Smarty_variable(null, true);
$var = trim($parameter['if condition']['var'], "'");
}
if (isset($compiler->template->tpl_vars[$var])) {
$compiler->template->tpl_vars[$var]->nocache = true;
} else {
$compiler->template->tpl_vars[$var] = new Smarty_Variable(null, true);
}
} else {
$_nocache = '';

View File

@ -1,306 +0,0 @@
<?php
/**
* Smarty Internal Plugin Config
*
* @package Smarty
* @subpackage Config
* @author Uwe Tews
*/
/**
* Smarty Internal Plugin Config
* Main class for config variables
*
* @package Smarty
* @subpackage Config
* @ignore
*/
class Smarty_Internal_Config
{
/**
* Smarty instance
*
* @var Smarty object
*/
public $smarty = null;
/**
* Object of config var storage
*
* @var object
*/
public $data = null;
/**
* Config resource
*
* @var string
*/
public $config_resource = null;
/**
* Compiled config file
*
* @var string
*/
public $compiled_config = null;
/**
* filepath of compiled config file
*
* @var string
*/
public $compiled_filepath = null;
/**
* Filemtime of compiled config Filemtime
*
* @var int
*/
public $compiled_timestamp = null;
/**
* flag if compiled config file is invalid and must be (re)compiled
*
* @var bool
*/
public $mustCompile = null;
/**
* Config file compiler object
*
* @var Smarty_Internal_Config_File_Compiler object
*/
public $compiler_object = null;
/**
* Constructor of config file object
*
* @param string $config_resource config file resource name
* @param Smarty $smarty Smarty instance
* @param object $data object for config vars storage
*/
public function __construct($config_resource, $smarty, $data = null)
{
$this->data = $data;
$this->smarty = $smarty;
$this->config_resource = $config_resource;
}
/**
* Returns the compiled filepath
*
* @return string the compiled filepath
*/
public function getCompiledFilepath()
{
return $this->compiled_filepath === null ?
($this->compiled_filepath = $this->buildCompiledFilepath()) :
$this->compiled_filepath;
}
/**
* Get file path.
*
* @return string
*/
public function buildCompiledFilepath()
{
$_compile_id = isset($this->smarty->compile_id) ? preg_replace('![^\w\|]+!', '_', $this->smarty->compile_id) : null;
$_flag = (int) $this->smarty->config_read_hidden + (int) $this->smarty->config_booleanize * 2
+ (int) $this->smarty->config_overwrite * 4;
$_filepath = sha1(realpath($this->source->filepath) . $_flag);
// if use_sub_dirs, break file into directories
if ($this->smarty->use_sub_dirs) {
$_filepath = substr($_filepath, 0, 2) . DS
. substr($_filepath, 2, 2) . DS
. substr($_filepath, 4, 2) . DS
. $_filepath;
}
$_compile_dir_sep = $this->smarty->use_sub_dirs ? DS : '^';
if (isset($_compile_id)) {
$_filepath = $_compile_id . $_compile_dir_sep . $_filepath;
}
$_compile_dir = $this->smarty->getCompileDir();
return $_compile_dir . $_filepath . '.' . basename($this->source->name) . '.config' . '.php';
}
/**
* Returns the timestamp of the compiled file
*
* @return integer the file timestamp
*/
public function getCompiledTimestamp()
{
return $this->compiled_timestamp === null
? ($this->compiled_timestamp = (file_exists($this->getCompiledFilepath())) ? filemtime($this->getCompiledFilepath()) : false)
: $this->compiled_timestamp;
}
/**
* Returns if the current config file must be compiled
* It does compare the timestamps of config source and the compiled config and checks the force compile configuration
*
* @return boolean true if the file must be compiled
*/
public function mustCompile()
{
return $this->mustCompile === null ?
$this->mustCompile = ($this->smarty->force_compile || $this->getCompiledTimestamp() === false || $this->smarty->compile_check && $this->getCompiledTimestamp() < $this->source->timestamp) :
$this->mustCompile;
}
/**
* Returns the compiled config file
* It checks if the config file must be compiled or just read the compiled version
*
* @return string the compiled config file
*/
public function getCompiledConfig()
{
if ($this->compiled_config === null) {
// see if template needs compiling.
if ($this->mustCompile()) {
$this->compileConfigSource();
} else {
$this->compiled_config = file_get_contents($this->getCompiledFilepath());
}
}
return $this->compiled_config;
}
/**
* Compiles the config files
*
* @throws Exception
*/
public function compileConfigSource()
{
// compile template
if (!is_object($this->compiler_object)) {
// load compiler
$this->compiler_object = new Smarty_Internal_Config_File_Compiler($this->smarty);
}
// compile locking
if ($this->smarty->compile_locking) {
if ($saved_timestamp = $this->getCompiledTimestamp()) {
touch($this->getCompiledFilepath());
}
}
// call compiler
try {
$this->compiler_object->compileSource($this);
}
catch (Exception $e) {
// restore old timestamp in case of error
if ($this->smarty->compile_locking && $saved_timestamp) {
touch($this->getCompiledFilepath(), $saved_timestamp);
}
throw $e;
}
// compiling succeeded
// write compiled template
Smarty_Internal_Write_File::writeFile($this->getCompiledFilepath(), $this->getCompiledConfig(), $this->smarty);
}
/**
* load config variables
*
* @param mixed $sections array of section names, single section or null
* @param string $scope global,parent or local
*
* @throws Exception
*/
public function loadConfigVars($sections = null, $scope = 'local')
{
if ($this->data instanceof Smarty_Internal_Template) {
$this->data->properties['file_dependency'][sha1($this->source->filepath)] = array($this->source->filepath, $this->source->timestamp, 'file');
}
if ($this->mustCompile()) {
$this->compileConfigSource();
}
// pointer to scope
if ($scope == 'local') {
$scope_ptr = $this->data;
} elseif ($scope == 'parent') {
if (isset($this->data->parent)) {
$scope_ptr = $this->data->parent;
} else {
$scope_ptr = $this->data;
}
} elseif ($scope == 'root' || $scope == 'global') {
$scope_ptr = $this->data;
while (isset($scope_ptr->parent)) {
$scope_ptr = $scope_ptr->parent;
}
}
$_config_vars = array();
include($this->getCompiledFilepath());
// copy global config vars
foreach ($_config_vars['vars'] as $variable => $value) {
if ($this->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) {
$scope_ptr->config_vars[$variable] = $value;
} else {
$scope_ptr->config_vars[$variable] = array_merge((array) $scope_ptr->config_vars[$variable], (array) $value);
}
}
// scan sections
if (!empty($sections)) {
foreach ((array) $sections as $this_section) {
if (isset($_config_vars['sections'][$this_section])) {
foreach ($_config_vars['sections'][$this_section]['vars'] as $variable => $value) {
if ($this->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) {
$scope_ptr->config_vars[$variable] = $value;
} else {
$scope_ptr->config_vars[$variable] = array_merge((array) $scope_ptr->config_vars[$variable], (array) $value);
}
}
}
}
}
}
/**
* set Smarty property in template context
*
* @param string $property_name property name
* @param mixed $value value
*
* @throws SmartyException if $property_name is not valid
*/
public function __set($property_name, $value)
{
switch ($property_name) {
case 'source':
case 'compiled':
$this->$property_name = $value;
return;
}
throw new SmartyException("invalid config property '$property_name'.");
}
/**
* get Smarty property in template context
*
* @param string $property_name property name
*
* @return \Smarty_Config_Source|\Smarty_Template_Compiled
* @throws SmartyException if $property_name is not valid
*/
public function __get($property_name)
{
switch ($property_name) {
case 'source':
if (empty($this->config_resource)) {
throw new SmartyException("Unable to parse resource name \"{$this->config_resource}\"");
}
$this->source = Smarty_Resource::config($this);
return $this->source;
case 'compiled':
$this->compiled = $this->source->getCompiled($this);
return $this->compiled;
}
throw new SmartyException("config attribute '$property_name' does not exist.");
}
}

View File

@ -17,6 +17,19 @@
*/
class Smarty_Internal_Config_File_Compiler
{
/**
* Lexer class name
*
* @var string
*/
public $lexer_class;
/**
* Parser class name
*
* @var string
*/
public $parser_class;
/**
* Lexer object
*
@ -41,9 +54,9 @@ class Smarty_Internal_Config_File_Compiler
/**
* Smarty object
*
* @var Smarty_Internal_Config object
* @var Smarty_Internal_Template object
*/
public $config;
public $template;
/**
* Compiled config data sections and variables
@ -52,40 +65,52 @@ class Smarty_Internal_Config_File_Compiler
*/
public $config_data = array();
/**
* compiled config data must always be written
*
* @var bool
*/
public $write_compiled_code = true;
/**
* Initialize compiler
*
* @param Smarty $smarty base instance
* @param string $lexer_class class name
* @param string $parser_class class name
* @param Smarty $smarty global instance
*/
public function __construct($smarty)
public function __construct($lexer_class, $parser_class, Smarty $smarty)
{
$this->smarty = $smarty;
// get required plugins
$this->lexer_class = $lexer_class;
$this->parser_class = $parser_class;
$this->smarty = $smarty;
$this->config_data['sections'] = array();
$this->config_data['vars'] = array();
}
/**
* Method to compile a Smarty template.
* Method to compile Smarty config source.
*
* @param Smarty_Internal_Config $config config object
* @param Smarty_Internal_Template $template
*
* @return bool true if compiling succeeded, false if it failed
* @return bool true if compiling succeeded, false if it failed
*/
public function compileSource(Smarty_Internal_Config $config)
public function compileTemplate(Smarty_Internal_Template $template)
{
/* here is where the compiling takes place. Smarty
tags in the templates are replaces with PHP code,
then written to compiled files. */
$this->config = $config;
// get config file source
$_content = $config->source->content . "\n";
// on empty template just return
if ($_content == '') {
$this->template = $template;
$this->template->properties['file_dependency'][$this->template->source->uid] = array($this->template->source->name, $this->template->source->timestamp, $this->template->source->type);
// on empty config just return
if ($template->source->content == '') {
return true;
}
if ($this->smarty->debugging) {
Smarty_Internal_Debug::start_compile($this->template);
}
// init the lexer/parser to compile the config file
$lex = new Smarty_Internal_Configfilelexer($_content, $this);
$parser = new Smarty_Internal_Configfileparser($lex, $this);
$lex = new $this->lexer_class(str_replace(array("\r\n", "\r"), "\n", $template->source->content) . "\n", $this);
$parser = new $this->parser_class($lex, $this);
if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) {
$mbEncoding = mb_internal_encoding();
@ -94,7 +119,6 @@ class Smarty_Internal_Config_File_Compiler
$mbEncoding = null;
}
if ($this->smarty->_parserdebug) {
$parser->PrintTrace();
}
@ -111,8 +135,15 @@ class Smarty_Internal_Config_File_Compiler
if ($mbEncoding) {
mb_internal_encoding($mbEncoding);
}
if ($this->smarty->debugging) {
Smarty_Internal_Debug::end_compile($this->template);
}
// template header code
$template_header = "<?php /* Smarty version " . Smarty::SMARTY_VERSION . ", created on " . strftime("%Y-%m-%d %H:%M:%S") . "\n";
$template_header .= " compiled from \"" . $this->template->source->filepath . "\" */ ?>\n";
$config->compiled_config = '<?php $_config_vars = ' . var_export($this->config_data, true) . '; ?>';
$code = '<?php Smarty_Internal_Extension_Config::loadConfigVars($_smarty_tpl, ' . var_export($this->config_data, true) . '); ?>';
return $template_header . Smarty_Internal_Extension_CodeFrame::create($this->template, $code);
}
/**
@ -129,13 +160,13 @@ class Smarty_Internal_Config_File_Compiler
{
$this->lex = Smarty_Internal_Configfilelexer::instance();
$this->parser = Smarty_Internal_Configfileparser::instance();
// get template source line which has error
// get config source line which has error
$line = $this->lex->line;
if (isset($args)) {
// $line--;
}
$match = preg_split("/\n/", $this->lex->data);
$error_text = "Syntax error in config file '{$this->config->source->filepath}' on line {$line} '{$match[$line - 1]}' ";
$error_text = "Syntax error in config file '{$this->template->source->filepath}' on line {$line} '{$match[$line - 1]}' ";
if (isset($args)) {
// individual error message
$error_text .= $args;

View File

@ -1,6 +1,7 @@
<?php
/**
* Smarty Internal Plugin Configfilelexer
*
* This is the lexer to break the config file source into tokens
*
* @package Smarty
@ -9,25 +10,134 @@
*/
/**
* Smarty Internal Plugin Configfilelexer
* Smarty_Internal_Configfilelexer
*
* This is the config file lexer.
* It is generated from the smarty_internal_configfilelexer.plex file
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
class Smarty_Internal_Configfilelexer
{
/**
* Source
*
* @var string
*/
public $data;
/**
* byte counter
*
* @var int
*/
public $counter;
/**
* token number
*
* @var int
*/
public $token;
/**
* token value
*
* @var string
*/
public $value;
public $node;
/**
* current line
*
* @var int
*/
public $line;
private $state = 1;
/**
* state number
*
* @var int
*/
public $state = 1;
/**
* Smarty object
*
* @var Smarty
*/
public $smarty = null;
/**
* compiler object
*
* @var Smarty_Internal_Config_File_Compiler
*/
private $compiler = null;
/**
* copy of config_booleanize
*
* @var bool
*/
private $configBooleanize = false;
/**
* trace file
*
* @var resource
*/
public $yyTraceFILE;
/**
* trace prompt
*
* @var string
*/
public $yyTracePrompt;
public $state_name = array(1 => 'START', 2 => 'VALUE', 3 => 'NAKED_STRING_VALUE', 4 => 'COMMENT', 5 => 'SECTION', 6 => 'TRIPPLE');
public $smarty_token_names = array( // Text for parser error messages
/**
* state names
*
* @var array
*/
public $state_name = array(1 => 'START', 2 => 'VALUE', 3 => 'NAKED_STRING_VALUE', 4 => 'COMMENT', 5 => 'SECTION',
6 => 'TRIPPLE');
/**
* storage for assembled token patterns
*
* @var sring
*/
private $yy_global_pattern1 = null;
private $yy_global_pattern2 = null;
private $yy_global_pattern3 = null;
private $yy_global_pattern4 = null;
private $yy_global_pattern5 = null;
private $yy_global_pattern6 = null;
/**
* token names
*
* @var array
*/
public $smarty_token_names = array( // Text for parser error messages
);
function __construct($data, $compiler)
/**
* constructor
*
* @param string $data template source
* @param Smarty_Internal_Config_File_Compiler $compiler
*/
function __construct($data, Smarty_Internal_Config_File_Compiler $compiler)
{
// set instance object
self::instance($this);
@ -39,6 +149,7 @@ class Smarty_Internal_Configfilelexer
$this->line = 1;
$this->compiler = $compiler;
$this->smarty = $compiler->smarty;
$this->configBooleanize = $this->smarty->config_booleanize;
}
public static function &instance($new_instance = null)
@ -57,6 +168,7 @@ class Smarty_Internal_Configfilelexer
}
private $_yy_state = 1;
private $_yy_stack = array();
public function yylex()
@ -97,41 +209,28 @@ class Smarty_Internal_Configfilelexer
public function yylex1()
{
$tokenMap = array(
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
);
if (!isset($this->yy_global_pattern1)) {
$this->yy_global_pattern1 = "/\G(#|;)|\G(\\[)|\G(\\])|\G(=)|\G([ \t\r]+)|\G(\n)|\G([0-9]*[a-zA-Z_]\\w*)|\G([\S\s])/isS";
}
if ($this->counter >= strlen($this->data)) {
return false; // end of input
}
$yy_global_pattern = "/\G(#|;)|\G(\\[)|\G(\\])|\G(=)|\G([ \t\r]+)|\G(\n)|\G([0-9]*[a-zA-Z_]\\w*)|\G([\S\s])/iS";
do {
if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) {
if (preg_match($this->yy_global_pattern1, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
if (!count($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
' an empty string. Input "' . substr($this->data,
$this->counter, 5) . '... state START');
if (strlen($yysubmatches[0]) < 200) {
$yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
} else {
$yymatches = array_filter($yymatches, 'strlen');
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . substr($this->data, $this->counter, 5) . '... state START');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value
$r = $this->{'yy_r1_' . $this->token}($yysubmatches);
$r = $this->{'yy_r1_' . $this->token}();
if ($r === null) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
@ -151,8 +250,7 @@ class Smarty_Internal_Configfilelexer
continue;
}
} else {
throw new Exception('Unexpected input at line' . $this->line .
': ' . $this->data[$this->counter]);
throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
}
break;
} while (true);
@ -160,52 +258,52 @@ class Smarty_Internal_Configfilelexer
const START = 1;
function yy_r1_1($yy_subpatterns)
function yy_r1_1()
{
$this->token = Smarty_Internal_Configfileparser::TPC_COMMENTSTART;
$this->yypushstate(self::COMMENT);
}
function yy_r1_2($yy_subpatterns)
function yy_r1_2()
{
$this->token = Smarty_Internal_Configfileparser::TPC_OPENB;
$this->yypushstate(self::SECTION);
}
function yy_r1_3($yy_subpatterns)
function yy_r1_3()
{
$this->token = Smarty_Internal_Configfileparser::TPC_CLOSEB;
}
function yy_r1_4($yy_subpatterns)
function yy_r1_4()
{
$this->token = Smarty_Internal_Configfileparser::TPC_EQUAL;
$this->yypushstate(self::VALUE);
}
function yy_r1_5($yy_subpatterns)
function yy_r1_5()
{
return false;
}
function yy_r1_6($yy_subpatterns)
function yy_r1_6()
{
$this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE;
}
function yy_r1_7($yy_subpatterns)
function yy_r1_7()
{
$this->token = Smarty_Internal_Configfileparser::TPC_ID;
}
function yy_r1_8($yy_subpatterns)
function yy_r1_8()
{
$this->token = Smarty_Internal_Configfileparser::TPC_OTHER;
@ -213,42 +311,28 @@ class Smarty_Internal_Configfilelexer
public function yylex2()
{
$tokenMap = array(
1 => 0,
2 => 0,
3 => 0,
4 => 0,
5 => 0,
6 => 0,
7 => 0,
8 => 0,
9 => 0,
);
if (!isset($this->yy_global_pattern2)) {
$this->yy_global_pattern2 = "/\G([ \t\r]+)|\G(\\d+\\.\\d+(?=[ \t\r]*[\n#;]))|\G(\\d+(?=[ \t\r]*[\n#;]))|\G(\"\"\")|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*'(?=[ \t\r]*[\n#;]))|\G(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"(?=[ \t\r]*[\n#;]))|\G([a-zA-Z]+(?=[ \t\r]*[\n#;]))|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/isS";
}
if ($this->counter >= strlen($this->data)) {
return false; // end of input
}
$yy_global_pattern = "/\G([ \t\r]+)|\G(\\d+\\.\\d+(?=[ \t\r]*[\n#;]))|\G(\\d+(?=[ \t\r]*[\n#;]))|\G(\"\"\")|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*'(?=[ \t\r]*[\n#;]))|\G(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"(?=[ \t\r]*[\n#;]))|\G([a-zA-Z]+(?=[ \t\r]*[\n#;]))|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/iS";
do {
if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) {
if (preg_match($this->yy_global_pattern2, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
if (!count($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
' an empty string. Input "' . substr($this->data,
$this->counter, 5) . '... state VALUE');
if (strlen($yysubmatches[0]) < 200) {
$yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
} else {
$yymatches = array_filter($yymatches, 'strlen');
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . substr($this->data, $this->counter, 5) . '... state VALUE');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value
$r = $this->{'yy_r2_' . $this->token}($yysubmatches);
$r = $this->{'yy_r2_' . $this->token}();
if ($r === null) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
@ -268,8 +352,7 @@ class Smarty_Internal_Configfilelexer
continue;
}
} else {
throw new Exception('Unexpected input at line' . $this->line .
': ' . $this->data[$this->counter]);
throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
}
break;
} while (true);
@ -277,51 +360,53 @@ class Smarty_Internal_Configfilelexer
const VALUE = 2;
function yy_r2_1($yy_subpatterns)
function yy_r2_1()
{
return false;
}
function yy_r2_2($yy_subpatterns)
function yy_r2_2()
{
$this->token = Smarty_Internal_Configfileparser::TPC_FLOAT;
$this->yypopstate();
}
function yy_r2_3($yy_subpatterns)
function yy_r2_3()
{
$this->token = Smarty_Internal_Configfileparser::TPC_INT;
$this->yypopstate();
}
function yy_r2_4($yy_subpatterns)
function yy_r2_4()
{
$this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES;
$this->yypushstate(self::TRIPPLE);
}
function yy_r2_5($yy_subpatterns)
function yy_r2_5()
{
$this->token = Smarty_Internal_Configfileparser::TPC_SINGLE_QUOTED_STRING;
$this->yypopstate();
}
function yy_r2_6($yy_subpatterns)
function yy_r2_6()
{
$this->token = Smarty_Internal_Configfileparser::TPC_DOUBLE_QUOTED_STRING;
$this->yypopstate();
}
function yy_r2_7($yy_subpatterns)
function yy_r2_7()
{
if (!$this->smarty->config_booleanize || !in_array(strtolower($this->value), Array("true", "false", "on", "off", "yes", "no"))) {
if (!$this->configBooleanize || !in_array(strtolower($this->value), Array("true", "false", "on", "off", "yes",
"no"))
) {
$this->yypopstate();
$this->yypushstate(self::NAKED_STRING_VALUE);
return true; //reprocess in new state
@ -331,14 +416,14 @@ class Smarty_Internal_Configfilelexer
}
}
function yy_r2_8($yy_subpatterns)
function yy_r2_8()
{
$this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
$this->yypopstate();
}
function yy_r2_9($yy_subpatterns)
function yy_r2_9()
{
$this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
@ -348,34 +433,28 @@ class Smarty_Internal_Configfilelexer
public function yylex3()
{
$tokenMap = array(
1 => 0,
);
if (!isset($this->yy_global_pattern3)) {
$this->yy_global_pattern3 = "/\G([^\n]+?(?=[ \t\r]*\n))/isS";
}
if ($this->counter >= strlen($this->data)) {
return false; // end of input
}
$yy_global_pattern = "/\G([^\n]+?(?=[ \t\r]*\n))/iS";
do {
if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) {
if (preg_match($this->yy_global_pattern3, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
if (!count($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
' an empty string. Input "' . substr($this->data,
$this->counter, 5) . '... state NAKED_STRING_VALUE');
if (strlen($yysubmatches[0]) < 200) {
$yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
} else {
$yymatches = array_filter($yymatches, 'strlen');
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . substr($this->data, $this->counter, 5) . '... state NAKED_STRING_VALUE');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value
$r = $this->{'yy_r3_' . $this->token}($yysubmatches);
$r = $this->{'yy_r3_' . $this->token}();
if ($r === null) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
@ -395,8 +474,7 @@ class Smarty_Internal_Configfilelexer
continue;
}
} else {
throw new Exception('Unexpected input at line' . $this->line .
': ' . $this->data[$this->counter]);
throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
}
break;
} while (true);
@ -404,7 +482,7 @@ class Smarty_Internal_Configfilelexer
const NAKED_STRING_VALUE = 3;
function yy_r3_1($yy_subpatterns)
function yy_r3_1()
{
$this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
@ -413,36 +491,28 @@ class Smarty_Internal_Configfilelexer
public function yylex4()
{
$tokenMap = array(
1 => 0,
2 => 0,
3 => 0,
);
if (!isset($this->yy_global_pattern4)) {
$this->yy_global_pattern4 = "/\G([ \t\r]+)|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/isS";
}
if ($this->counter >= strlen($this->data)) {
return false; // end of input
}
$yy_global_pattern = "/\G([ \t\r]+)|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/iS";
do {
if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) {
if (preg_match($this->yy_global_pattern4, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
if (!count($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
' an empty string. Input "' . substr($this->data,
$this->counter, 5) . '... state COMMENT');
if (strlen($yysubmatches[0]) < 200) {
$yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
} else {
$yymatches = array_filter($yymatches, 'strlen');
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . substr($this->data, $this->counter, 5) . '... state COMMENT');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value
$r = $this->{'yy_r4_' . $this->token}($yysubmatches);
$r = $this->{'yy_r4_' . $this->token}();
if ($r === null) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
@ -462,8 +532,7 @@ class Smarty_Internal_Configfilelexer
continue;
}
} else {
throw new Exception('Unexpected input at line' . $this->line .
': ' . $this->data[$this->counter]);
throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
}
break;
} while (true);
@ -471,19 +540,19 @@ class Smarty_Internal_Configfilelexer
const COMMENT = 4;
function yy_r4_1($yy_subpatterns)
function yy_r4_1()
{
return false;
}
function yy_r4_2($yy_subpatterns)
function yy_r4_2()
{
$this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
}
function yy_r4_3($yy_subpatterns)
function yy_r4_3()
{
$this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE;
@ -492,35 +561,28 @@ class Smarty_Internal_Configfilelexer
public function yylex5()
{
$tokenMap = array(
1 => 0,
2 => 0,
);
if (!isset($this->yy_global_pattern5)) {
$this->yy_global_pattern5 = "/\G(\\.)|\G(.*?(?=[\.=[\]\r\n]))/isS";
}
if ($this->counter >= strlen($this->data)) {
return false; // end of input
}
$yy_global_pattern = "/\G(\\.)|\G(.*?(?=[\.=[\]\r\n]))/iS";
do {
if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) {
if (preg_match($this->yy_global_pattern5, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
if (!count($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
' an empty string. Input "' . substr($this->data,
$this->counter, 5) . '... state SECTION');
if (strlen($yysubmatches[0]) < 200) {
$yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
} else {
$yymatches = array_filter($yymatches, 'strlen');
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . substr($this->data, $this->counter, 5) . '... state SECTION');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value
$r = $this->{'yy_r5_' . $this->token}($yysubmatches);
$r = $this->{'yy_r5_' . $this->token}();
if ($r === null) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
@ -540,8 +602,7 @@ class Smarty_Internal_Configfilelexer
continue;
}
} else {
throw new Exception('Unexpected input at line' . $this->line .
': ' . $this->data[$this->counter]);
throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
}
break;
} while (true);
@ -549,13 +610,13 @@ class Smarty_Internal_Configfilelexer
const SECTION = 5;
function yy_r5_1($yy_subpatterns)
function yy_r5_1()
{
$this->token = Smarty_Internal_Configfileparser::TPC_DOT;
}
function yy_r5_2($yy_subpatterns)
function yy_r5_2()
{
$this->token = Smarty_Internal_Configfileparser::TPC_SECTION;
@ -564,35 +625,28 @@ class Smarty_Internal_Configfilelexer
public function yylex6()
{
$tokenMap = array(
1 => 0,
2 => 0,
);
if (!isset($this->yy_global_pattern6)) {
$this->yy_global_pattern6 = "/\G(\"\"\"(?=[ \t\r]*[\n#;]))|\G([\S\s])/isS";
}
if ($this->counter >= strlen($this->data)) {
return false; // end of input
}
$yy_global_pattern = "/\G(\"\"\"(?=[ \t\r]*[\n#;]))|\G([\S\s])/iS";
do {
if (preg_match($yy_global_pattern, $this->data, $yymatches, null, $this->counter)) {
if (preg_match($this->yy_global_pattern6, $this->data, $yymatches, null, $this->counter)) {
$yysubmatches = $yymatches;
$yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
if (!count($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
' an empty string. Input "' . substr($this->data,
$this->counter, 5) . '... state TRIPPLE');
if (strlen($yysubmatches[0]) < 200) {
$yymatches = preg_grep("/(.|\s)+/", $yysubmatches);
} else {
$yymatches = array_filter($yymatches, 'strlen');
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . substr($this->data, $this->counter, 5) . '... state TRIPPLE');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
if ($tokenMap[$this->token]) {
// extract sub-patterns for passing to lex function
$yysubmatches = array_slice($yysubmatches, $this->token + 1,
$tokenMap[$this->token]);
} else {
$yysubmatches = array();
}
$this->value = current($yymatches); // token value
$r = $this->{'yy_r6_' . $this->token}($yysubmatches);
$r = $this->{'yy_r6_' . $this->token}();
if ($r === null) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
@ -612,8 +666,7 @@ class Smarty_Internal_Configfilelexer
continue;
}
} else {
throw new Exception('Unexpected input at line' . $this->line .
': ' . $this->data[$this->counter]);
throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[$this->counter]);
}
break;
} while (true);
@ -621,7 +674,7 @@ class Smarty_Internal_Configfilelexer
const TRIPPLE = 6;
function yy_r6_1($yy_subpatterns)
function yy_r6_1()
{
$this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES_END;
@ -629,7 +682,7 @@ class Smarty_Internal_Configfilelexer
$this->yypushstate(self::START);
}
function yy_r6_2($yy_subpatterns)
function yy_r6_2()
{
$to = strlen($this->data);
@ -642,5 +695,5 @@ class Smarty_Internal_Configfilelexer
$this->value = substr($this->data, $this->counter, $to - $this->counter);
$this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_TEXT;
}
}
}

View File

@ -55,12 +55,12 @@ class Smarty_Internal_Data
if (is_array($tpl_var)) {
foreach ($tpl_var as $_key => $_val) {
if ($_key != '') {
$this->tpl_vars[$_key] = new Smarty_variable($_val, $nocache);
$this->tpl_vars[$_key] = new Smarty_Variable($_val, $nocache);
}
}
} else {
if ($tpl_var != '') {
$this->tpl_vars[$tpl_var] = new Smarty_variable($value, $nocache);
$this->tpl_vars[$tpl_var] = new Smarty_Variable($value, $nocache);
}
}
@ -79,7 +79,7 @@ class Smarty_Internal_Data
public function assignGlobal($varname, $value = null, $nocache = false)
{
if ($varname != '') {
Smarty::$global_tpl_vars[$varname] = new Smarty_variable($value, $nocache);
Smarty::$global_tpl_vars[$varname] = new Smarty_Variable($value, $nocache);
$ptr = $this;
while ($ptr instanceof Smarty_Internal_Template) {
$ptr->tpl_vars[$varname] = clone Smarty::$global_tpl_vars[$varname];
@ -102,8 +102,8 @@ class Smarty_Internal_Data
public function assignByRef($tpl_var, &$value, $nocache = false)
{
if ($tpl_var != '') {
$this->tpl_vars[$tpl_var] = new Smarty_variable(null, $nocache);
$this->tpl_vars[$tpl_var]->value = & $value;
$this->tpl_vars[$tpl_var] = new Smarty_Variable(null, $nocache);
$this->tpl_vars[$tpl_var]->value = &$value;
}
return $this;
@ -127,8 +127,8 @@ class Smarty_Internal_Data
if ($_key != '') {
if (!isset($this->tpl_vars[$_key])) {
$tpl_var_inst = $this->getVariable($_key, null, true, false);
if ($tpl_var_inst instanceof Undefined_Smarty_Variable) {
$this->tpl_vars[$_key] = new Smarty_variable(null, $nocache);
if ($tpl_var_inst instanceof Smarty_Undefined_Variable) {
$this->tpl_vars[$_key] = new Smarty_Variable(null, $nocache);
} else {
$this->tpl_vars[$_key] = clone $tpl_var_inst;
}
@ -149,8 +149,8 @@ class Smarty_Internal_Data
if ($tpl_var != '' && isset($value)) {
if (!isset($this->tpl_vars[$tpl_var])) {
$tpl_var_inst = $this->getVariable($tpl_var, null, true, false);
if ($tpl_var_inst instanceof Undefined_Smarty_Variable) {
$this->tpl_vars[$tpl_var] = new Smarty_variable(null, $nocache);
if ($tpl_var_inst instanceof Smarty_Undefined_Variable) {
$this->tpl_vars[$tpl_var] = new Smarty_Variable(null, $nocache);
} else {
$this->tpl_vars[$tpl_var] = clone $tpl_var_inst;
}
@ -184,17 +184,17 @@ class Smarty_Internal_Data
{
if ($tpl_var != '' && isset($value)) {
if (!isset($this->tpl_vars[$tpl_var])) {
$this->tpl_vars[$tpl_var] = new Smarty_variable();
$this->tpl_vars[$tpl_var] = new Smarty_Variable();
}
if (!is_array($this->tpl_vars[$tpl_var]->value)) {
settype($this->tpl_vars[$tpl_var]->value, 'array');
}
if ($merge && is_array($value)) {
foreach ($value as $_key => $_val) {
$this->tpl_vars[$tpl_var]->value[$_key] = & $value[$_key];
$this->tpl_vars[$tpl_var]->value[$_key] = &$value[$_key];
}
} else {
$this->tpl_vars[$tpl_var]->value[] = & $value;
$this->tpl_vars[$tpl_var]->value[] = &$value;
}
}
@ -205,7 +205,7 @@ class Smarty_Internal_Data
* Returns a single or all template variables
*
* @param string $varname variable name or null
* @param object $_ptr optional pointer to data object
* @param object $_ptr optional pointer to data object
* @param boolean $search_parents include parent templates?
*
* @return string variable value or or array of variables
@ -292,9 +292,7 @@ class Smarty_Internal_Data
public function configLoad($config_file, $sections = null)
{
// load Config class
$config = new Smarty_Internal_Config($config_file, $this->smarty, $this);
$config->loadConfigVars($sections);
Smarty_Internal_Extension_Config::configLoad($this, $config_file, $sections);
return $this;
}
@ -329,12 +327,13 @@ class Smarty_Internal_Data
// found it, return it
return Smarty::$global_tpl_vars[$variable];
}
if ($this->smarty->error_unassigned && $error_enable) {
$smarty = isset($this->smarty) ? $this->smarty : $this;
if ($smarty->error_unassigned && $error_enable) {
// force a notice
$x = $$variable;
}
return new Undefined_Smarty_Variable;
return new Smarty_Undefined_Variable;
}
/**
@ -347,21 +346,32 @@ class Smarty_Internal_Data
*/
public function getConfigVariable($variable, $error_enable = true)
{
$_ptr = $this;
while ($_ptr !== null) {
if (isset($_ptr->config_vars[$variable])) {
// found it, return it
return $_ptr->config_vars[$variable];
}
// not found, try at parent
$_ptr = $_ptr->parent;
}
if ($this->smarty->error_unassigned && $error_enable) {
// force a notice
$x = $$variable;
}
return Smarty_Internal_Extension_Config::getConfigVariable($this, $variable, $error_enable = true);
}
return null;
/**
* Returns a single or all config variables
*
* @param string $varname variable name or null
* @param bool $search_parents
*
* @return string variable value or or array of variables
*/
public function getConfigVars($varname = null, $search_parents = true)
{
return Smarty_Internal_Extension_Config::getConfigVars($this, $varname, $search_parents);
}
/**
* Deassigns a single or all config variables
*
* @param string $varname variable name or null
*
* @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
*/
public function clearConfig($varname = null)
{
return Smarty_Internal_Extension_Config::clearConfig($this, $varname);
}
/**
@ -384,193 +394,11 @@ class Smarty_Internal_Data
return $_result;
}
if ($this->smarty->error_unassigned) {
$smarty = isset($this->smarty) ? $this->smarty : $this;
if ($smarty->error_unassigned) {
throw new SmartyException('Undefined stream variable "' . $variable . '"');
} else {
return null;
}
}
/**
* Returns a single or all config variables
*
* @param string $varname variable name or null
* @param bool $search_parents
*
* @return string variable value or or array of variables
*/
public function getConfigVars($varname = null, $search_parents = true)
{
$_ptr = $this;
$var_array = array();
while ($_ptr !== null) {
if (isset($varname)) {
if (isset($_ptr->config_vars[$varname])) {
return $_ptr->config_vars[$varname];
}
} else {
$var_array = array_merge($_ptr->config_vars, $var_array);
}
// not found, try at parent
if ($search_parents) {
$_ptr = $_ptr->parent;
} else {
$_ptr = null;
}
}
if (isset($varname)) {
return '';
} else {
return $var_array;
}
}
/**
* Deassigns a single or all config variables
*
* @param string $varname variable name or null
*
* @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
*/
public function clearConfig($varname = null)
{
if (isset($varname)) {
unset($this->config_vars[$varname]);
} else {
$this->config_vars = array();
}
return $this;
}
}
/**
* class for the Smarty data object
* The Smarty data object will hold Smarty variables in the current scope
*
* @package Smarty
* @subpackage Template
*/
class Smarty_Data extends Smarty_Internal_Data
{
/**
* Smarty object
*
* @var Smarty
*/
public $smarty = null;
/**
* create Smarty data object
*
* @param Smarty|array $_parent parent template
* @param Smarty|Smarty_Internal_Template $smarty global smarty instance
*
* @throws SmartyException
*/
public function __construct($_parent = null, $smarty = null)
{
$this->smarty = $smarty;
if (is_object($_parent)) {
// when object set up back pointer
$this->parent = $_parent;
} elseif (is_array($_parent)) {
// set up variable values
foreach ($_parent as $_key => $_val) {
$this->tpl_vars[$_key] = new Smarty_variable($_val);
}
} elseif ($_parent != null) {
throw new SmartyException("Wrong type for template variables");
}
}
}
/**
* class for the Smarty variable object
* This class defines the Smarty variable object
*
* @package Smarty
* @subpackage Template
*/
class Smarty_Variable
{
/**
* template variable
*
* @var mixed
*/
public $value = null;
/**
* if true any output of this variable will be not cached
*
* @var boolean
*/
public $nocache = false;
/**
* the scope the variable will have (local,parent or root)
*
* @var int
*/
public $scope = Smarty::SCOPE_LOCAL;
/**
* create Smarty variable object
*
* @param mixed $value the value to assign
* @param boolean $nocache if true any output of this variable will be not cached
* @param int $scope the scope the variable will have (local,parent or root)
*/
public function __construct($value = null, $nocache = false, $scope = Smarty::SCOPE_LOCAL)
{
$this->value = $value;
$this->nocache = $nocache;
$this->scope = $scope;
}
/**
* <<magic>> String conversion
*
* @return string
*/
public function __toString()
{
return (string) $this->value;
}
}
/**
* class for undefined variable object
* This class defines an object for undefined variable handling
*
* @package Smarty
* @subpackage Template
*/
class Undefined_Smarty_Variable
{
/**
* Returns FALSE for 'nocache' and NULL otherwise.
*
* @param string $name
*
* @return bool
*/
public function __get($name)
{
if ($name == 'nocache') {
return false;
} else {
return null;
}
}
/**
* Always returns an empty string.
*
* @return string
*/
public function __toString()
{
return "";
}
}

View File

@ -1,7 +1,7 @@
<?php
/**
* Smarty Internal Plugin Debug
* Class to collect data for the Smarty Debugging Consol
* Class to collect data for the Smarty Debugging Console
*
* @package Smarty
* @subpackage Debug
@ -31,155 +31,230 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
public static $ignore_uid = array();
/**
* Ignore template
* Index of display() and fetch() calls
*
* @param object $template
* @var int
*/
public static function ignore($template)
public static $index = 0;
/**
* Counter for window offset
*
* @var int
*/
public static $offset = 0;
/**
* Start logging template
*
* @param \Smarty_Internal_Template $template template
* @param null $mode true: display false: fetch null: subtemolate
*/
public static function start_template(Smarty_Internal_Template $template, $mode = null)
{
// calculate Uid if not already done
if ($template->source->uid == '') {
$template->source->filepath;
if (isset($mode)) {
self::$index ++;
self::$offset ++;
self::$template_data[self::$index] = null;
}
self::$ignore_uid[$template->source->uid] = true;
}
/**
* Start logging of compile time
*
* @param object $template
*/
public static function start_compile($template)
{
static $_is_stringy = array('string' => true, 'eval' => true);
if (!empty($template->compiler->trace_uid)) {
$key = $template->compiler->trace_uid;
if (!isset(self::$template_data[$key])) {
if (isset($_is_stringy[$template->source->type])) {
self::$template_data[$key]['name'] = '\'' . substr($template->source->name, 0, 25) . '...\'';
} else {
self::$template_data[$key]['name'] = $template->source->filepath;
}
self::$template_data[$key]['compile_time'] = 0;
self::$template_data[$key]['render_time'] = 0;
self::$template_data[$key]['cache_time'] = 0;
}
} else {
if (isset(self::$ignore_uid[$template->source->uid])) {
return;
}
$key = self::get_key($template);
}
self::$template_data[$key]['start_time'] = microtime(true);
}
/**
* End logging of compile time
*
* @param object $template
*/
public static function end_compile($template)
{
if (!empty($template->compiler->trace_uid)) {
$key = $template->compiler->trace_uid;
} else {
if (isset(self::$ignore_uid[$template->source->uid])) {
return;
}
$key = self::get_key($template);
}
self::$template_data[$key]['compile_time'] += microtime(true) - self::$template_data[$key]['start_time'];
}
/**
* Start logging of render time
*
* @param object $template
*/
public static function start_render($template)
{
$key = self::get_key($template);
self::$template_data[$key]['start_time'] = microtime(true);
}
/**
* End logging of compile time
*
* @param object $template
*/
public static function end_render($template)
{
$key = self::get_key($template);
self::$template_data[$key]['render_time'] += microtime(true) - self::$template_data[$key]['start_time'];
}
/**
* Start logging of cache time
*
* @param object $template cached template
*/
public static function start_cache($template)
{
$key = self::get_key($template);
self::$template_data[$key]['start_time'] = microtime(true);
self::$template_data[self::$index][$key]['start_template_time'] = microtime(true);
}
/**
* End logging of cache time
*
* @param object $template cached template
* @param \Smarty_Internal_Template $template cached template
*/
public static function end_cache($template)
public static function end_template(Smarty_Internal_Template $template)
{
$key = self::get_key($template);
self::$template_data[$key]['cache_time'] += microtime(true) - self::$template_data[$key]['start_time'];
self::$template_data[self::$index][$key]['total_time'] += microtime(true) - self::$template_data[self::$index][$key]['start_template_time'];
self::$template_data[self::$index][$key]['properties'] = $template->properties;
}
/**
* Opens a window for the Smarty Debugging Consol and display the data
* Start logging of compile time
*
* @param \Smarty_Internal_Template $template
*/
public static function start_compile(Smarty_Internal_Template $template)
{
static $_is_stringy = array('string' => true, 'eval' => true);
if (!empty($template->compiler->trace_uid)) {
$key = $template->compiler->trace_uid;
if (!isset(self::$template_data[self::$index][$key])) {
if (isset($_is_stringy[$template->source->type])) {
self::$template_data[self::$index][$key]['name'] = '\'' . substr($template->source->name, 0, 25) . '...\'';
} else {
self::$template_data[self::$index][$key]['name'] = $template->source->filepath;
}
self::$template_data[self::$index][$key]['compile_time'] = 0;
self::$template_data[self::$index][$key]['render_time'] = 0;
self::$template_data[self::$index][$key]['cache_time'] = 0;
}
} else {
if (isset(self::$ignore_uid[$template->source->uid])) {
return;
}
$key = self::get_key($template);
}
self::$template_data[self::$index][$key]['start_time'] = microtime(true);
}
/**
* End logging of compile time
*
* @param \Smarty_Internal_Template $template
*/
public static function end_compile(Smarty_Internal_Template $template)
{
if (!empty($template->compiler->trace_uid)) {
$key = $template->compiler->trace_uid;
} else {
if (isset(self::$ignore_uid[$template->source->uid])) {
return;
}
$key = self::get_key($template);
}
self::$template_data[self::$index][$key]['compile_time'] += microtime(true) - self::$template_data[self::$index][$key]['start_time'];
}
/**
* Start logging of render time
*
* @param \Smarty_Internal_Template $template
*/
public static function start_render(Smarty_Internal_Template $template)
{
$key = self::get_key($template);
self::$template_data[self::$index][$key]['start_time'] = microtime(true);
}
/**
* End logging of compile time
*
* @param \Smarty_Internal_Template $template
*/
public static function end_render(Smarty_Internal_Template $template)
{
$key = self::get_key($template);
self::$template_data[self::$index][$key]['render_time'] += microtime(true) - self::$template_data[self::$index][$key]['start_time'];
}
/**
* Start logging of cache time
*
* @param \Smarty_Internal_Template $template cached template
*/
public static function start_cache(Smarty_Internal_Template $template)
{
$key = self::get_key($template);
self::$template_data[self::$index][$key]['start_time'] = microtime(true);
}
/**
* End logging of cache time
*
* @param \Smarty_Internal_Template $template cached template
*/
public static function end_cache(Smarty_Internal_Template $template)
{
$key = self::get_key($template);
self::$template_data[self::$index][$key]['cache_time'] += microtime(true) - self::$template_data[self::$index][$key]['start_time'];
}
/**
* Register template object
*
* @param \Smarty_Internal_Template $template cached template
*/
public static function register_template(Smarty_Internal_Template $template)
{
}
/**
* Register data object
*
* @param \Smarty_Data $data data object
*/
public static function register_data(Smarty_Data $data)
{
}
/**
* Opens a window for the Smarty Debugging Console and display the data
*
* @param Smarty_Internal_Template|Smarty $obj object to debug
* @param bool $full
*/
public static function display_debug($obj)
public static function display_debug($obj, $full = false)
{
if (!$full) {
self::$offset ++;
$savedIndex = self::$index;
self::$index = 9999;
}
if ($obj instanceof Smarty) {
$smarty = $obj;
} else {
$smarty = $obj->smarty;
}
// create fresh instance of smarty for displaying the debug console
// to avoid problems if the application did overload the Smarty class
$debObj = new Smarty();
// copy the working dirs from application
$debObj->setCompileDir($smarty->getCompileDir());
// init properties by hand as user may have edited the original Smarty class
$debObj->setPluginsDir(is_dir(__DIR__ . '/../plugins') ? __DIR__ . '/../plugins' : $smarty->getPluginsDir());
$debObj->force_compile = false;
$debObj->compile_check = true;
$debObj->left_delimiter = '{';
$debObj->right_delimiter = '}';
$debObj->security_policy = null;
$debObj->debugging = false;
$debObj->debugging_ctrl = 'NONE';
$debObj->error_reporting = E_ALL & ~E_NOTICE;
$debObj->debug_tpl = isset($smarty->debug_tpl) ? $smarty->debug_tpl : 'file:' . __DIR__ . '/../debug.tpl';
$debObj->registered_plugins = array();
$debObj->registered_resources = array();
$debObj->registered_filters = array();
$debObj->autoload_filters = array();
$debObj->default_modifiers = array();
$debObj->escape_html = true;
$debObj->caching = false;
$debObj->compile_id = null;
$debObj->cache_id = null;
// prepare information of assigned variables
$ptr = self::get_debug_vars($obj);
if ($obj instanceof Smarty) {
$smarty = clone $obj;
} else {
$smarty = clone $obj->smarty;
}
$_assigned_vars = $ptr->tpl_vars;
ksort($_assigned_vars);
$_config_vars = $ptr->config_vars;
ksort($_config_vars);
$smarty->registered_filters = array();
$smarty->autoload_filters = array();
$smarty->default_modifiers = array();
$smarty->force_compile = false;
$smarty->left_delimiter = '{';
$smarty->right_delimiter = '}';
$smarty->debugging = false;
$smarty->debugging_ctrl = 'NONE';
$smarty->force_compile = false;
$_template = new Smarty_Internal_Template($smarty->debug_tpl, $smarty);
$_template->caching = false;
$_template->disableSecurity();
$_template->cache_id = null;
$_template->compile_id = null;
$debugging = $smarty->debugging;
$_template = new Smarty_Internal_Template($debObj->debug_tpl, $debObj);
if ($obj instanceof Smarty_Internal_Template) {
$_template->assign('template_name', $obj->source->type . ':' . $obj->source->name);
}
if ($obj instanceof Smarty) {
$_template->assign('template_data', self::$template_data);
if ($obj instanceof Smarty || $full) {
$_template->assign('template_data', self::$template_data[self::$index]);
} else {
$_template->assign('template_data', null);
}
$_template->assign('assigned_vars', $_assigned_vars);
$_template->assign('config_vars', $_config_vars);
$_template->assign('execution_time', microtime(true) - $smarty->start_time);
$_template->assign('display_mode', $debugging == 2 || !$full);
$_template->assign('offset', self::$offset * 50);
echo $_template->fetch();
if (isset($full)) {
self::$index --;
}
if (!$full) {
self::$index = $savedIndex;
}
}
/**
@ -191,29 +266,77 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
*/
public static function get_debug_vars($obj)
{
$config_vars = $obj->config_vars;
$config_vars = array();
foreach ($obj->config_vars as $key => $var) {
$config_vars[$key]['value'] = $var;
if ($obj instanceof Smarty_Internal_Template) {
$config_vars[$key]['scope'] = $obj->source->type . ':' . $obj->source->name;
} elseif ($obj instanceof Smarty_Data) {
$tpl_vars[$key]['scope'] = $obj->dataObjectName;
} else {
$config_vars[$key]['scope'] = 'Smarty object';
}
}
$tpl_vars = array();
foreach ($obj->tpl_vars as $key => $var) {
$tpl_vars[$key] = clone $var;
foreach ($var as $varkey => $varvalue) {
if ($varkey == 'value') {
$tpl_vars[$key][$varkey] = $varvalue;
} else {
if ($varkey == 'nocache') {
if ($varvalue == true) {
$tpl_vars[$key][$varkey] = $varvalue;
}
} else {
if ($varkey != 'scope' || $varvalue !== 0) {
$tpl_vars[$key]['attributes'][$varkey] = $varvalue;
}
}
}
}
if ($obj instanceof Smarty_Internal_Template) {
$tpl_vars[$key]->scope = $obj->source->type . ':' . $obj->source->name;
$tpl_vars[$key]['scope'] = $obj->source->type . ':' . $obj->source->name;
} elseif ($obj instanceof Smarty_Data) {
$tpl_vars[$key]->scope = 'Data object';
$tpl_vars[$key]['scope'] = $obj->dataObjectName;
} else {
$tpl_vars[$key]->scope = 'Smarty root';
$tpl_vars[$key]['scope'] = 'Smarty object';
}
}
if (isset($obj->parent)) {
$parent = self::get_debug_vars($obj->parent);
foreach ($parent->tpl_vars as $name => $pvar) {
if (isset($tpl_vars[$name]) && $tpl_vars[$name]['value'] === $pvar['value']) {
$tpl_vars[$name]['scope'] = $pvar['scope'];
}
}
$tpl_vars = array_merge($parent->tpl_vars, $tpl_vars);
foreach ($parent->config_vars as $name => $pvar) {
if (isset($config_vars[$name]) && $config_vars[$name]['value'] === $pvar['value']) {
$config_vars[$name]['scope'] = $pvar['scope'];
}
}
$config_vars = array_merge($parent->config_vars, $config_vars);
} else {
foreach (Smarty::$global_tpl_vars as $name => $var) {
if (!array_key_exists($name, $tpl_vars)) {
$clone = clone $var;
$clone->scope = 'Global';
$tpl_vars[$name] = $clone;
foreach (Smarty::$global_tpl_vars as $key => $var) {
if (!array_key_exists($key, $tpl_vars)) {
foreach ($var as $varkey => $varvalue) {
if ($varkey == 'value') {
$tpl_vars[$key][$varkey] = $varvalue;
} else {
if ($varkey == 'nocache') {
if ($varvalue == true) {
$tpl_vars[$key][$varkey] = $varvalue;
}
} else {
if ($varkey != 'scope' || $varvalue !== 0) {
$tpl_vars[$key]['attributes'][$varkey] = $varvalue;
}
}
}
}
$tpl_vars[$key]['scope'] = 'Global';
}
}
}
@ -224,11 +347,11 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
/**
* Return key into $template_data for template
*
* @param object $template template object
* @param \Smarty_Internal_Template $template template object
*
* @return string key into $template_data
*/
private static function get_key($template)
private static function get_key(Smarty_Internal_Template $template)
{
static $_is_stringy = array('string' => true, 'eval' => true);
// calculate Uid if not already done
@ -236,19 +359,66 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
$template->source->filepath;
}
$key = $template->source->uid;
if (isset(self::$template_data[$key])) {
if (isset(self::$template_data[self::$index][$key])) {
return $key;
} else {
if (isset($_is_stringy[$template->source->type])) {
self::$template_data[$key]['name'] = '\'' . substr($template->source->name, 0, 25) . '...\'';
self::$template_data[self::$index][$key]['name'] = '\'' . substr($template->source->name, 0, 25) . '...\'';
} else {
self::$template_data[$key]['name'] = $template->source->filepath;
self::$template_data[self::$index][$key]['name'] = $template->source->filepath;
}
self::$template_data[$key]['compile_time'] = 0;
self::$template_data[$key]['render_time'] = 0;
self::$template_data[$key]['cache_time'] = 0;
self::$template_data[self::$index][$key]['compile_time'] = 0;
self::$template_data[self::$index][$key]['render_time'] = 0;
self::$template_data[self::$index][$key]['cache_time'] = 0;
self::$template_data[self::$index][$key]['total_time'] = 0;
return $key;
}
}
/**
* Ignore template
*
* @param \Smarty_Internal_Template $template
*/
public static function ignore(Smarty_Internal_Template $template)
{
// calculate Uid if not already done
if ($template->source->uid == '') {
$template->source->filepath;
}
self::$ignore_uid[$template->source->uid] = true;
}
/**
* handle 'URL' debugging mode
*
* @param Smarty_Internal_Template $_template
*/
public static function debugUrl(Smarty_Internal_Template $_template)
{
if (isset($_SERVER['QUERY_STRING'])) {
$_query_string = $_SERVER['QUERY_STRING'];
} else {
$_query_string = '';
}
if (false !== strpos($_query_string, $_template->smarty->smarty_debug_id)) {
if (false !== strpos($_query_string, $_template->smarty->smarty_debug_id . '=on')) {
// enable debugging for this browser session
setcookie('SMARTY_DEBUG', true);
$_template->smarty->debugging = true;
} elseif (false !== strpos($_query_string, $_template->smarty->smarty_debug_id . '=off')) {
// disable debugging for this browser session
setcookie('SMARTY_DEBUG', false);
$_template->smarty->debugging = false;
} else {
// enable debugging for this page
$_template->smarty->debugging = true;
}
} else {
if (isset($_COOKIE['SMARTY_DEBUG'])) {
$_template->smarty->debugging = true;
}
}
}
}

View File

@ -0,0 +1,127 @@
<?php
/**
* Smarty Internal Extension
* This file contains the Smarty template extension to create a code frame
*
* @package Smarty
* @subpackage Template
* @author Uwe Tews
*/
/**
* Class Smarty_Internal_Extension_CodeFrame
* Create code frame for compiled and cached templates
*/
class Smarty_Internal_Extension_CodeFrame
{
/**
* Create code frame for compiled and cached templates
*
* @param Smarty_Internal_Template $_template
* @param string $content optional template content
* @param bool $cache flag for cache file
*
* @return string
*/
public static function create(Smarty_Internal_Template $_template, $content = '', $cache = false)
{
// build property code
$_template->properties['has_nocache_code'] = $_template->has_nocache_code || !empty($_template->required_plugins['nocache']);
$_template->properties['version'] = Smarty::SMARTY_VERSION;
if (!isset($_template->properties['unifunc'])) {
$_template->properties['unifunc'] = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
}
$properties = $_template->properties;
if (!$cache) {
unset($properties['tpl_function']);
if (!empty($_template->compiler->templateProperties)) {
$properties['tpl_function'] = $_template->compiler->templateProperties['tpl_function'];
}
}
$output = "<?php\n";
$output .= "/*%%SmartyHeaderCode:{$_template->properties['nocache_hash']}%%*/\n";
if ($_template->smarty->direct_access_security) {
$output .= "if(!defined('SMARTY_DIR')) exit('no direct access allowed');\n";
}
$output .= "\$_valid = \$_smarty_tpl->decodeProperties(" . var_export($properties, true) . ',' . ($cache ? 'true' : 'false') . ");\n";
$output .= "/*/%%SmartyHeaderCode%%*/\n";
$output .= "if (\$_valid && !is_callable('{$_template->properties['unifunc']}')) {\n";
$output .= "function {$_template->properties['unifunc']} (\$_smarty_tpl) {\n";
// include code for plugins
if (!$cache) {
if (!empty($_template->required_plugins['compiled'])) {
foreach ($_template->required_plugins['compiled'] as $tmp) {
foreach ($tmp as $data) {
$file = addslashes($data['file']);
if (is_Array($data['function'])) {
$output .= "if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) require_once '{$file}';\n";
} else {
$output .= "if (!is_callable('{$data['function']}')) require_once '{$file}';\n";
}
}
}
}
if (!empty($_template->required_plugins['nocache'])) {
$_template->has_nocache_code = true;
$output .= "echo '/*%%SmartyNocache:{$_template->properties['nocache_hash']}%%*/<?php \$_smarty = \$_smarty_tpl->smarty; ";
foreach ($_template->required_plugins['nocache'] as $tmp) {
foreach ($tmp as $data) {
$file = addslashes($data['file']);
if (is_Array($data['function'])) {
$output .= addslashes("if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) require_once '{$file}';\n");
} else {
$output .= addslashes("if (!is_callable('{$data['function']}')) require_once '{$file}';\n");
}
}
}
$output .= "?>/*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%*/';\n";
}
}
$output .= "?>\n";
$output = self::appendCode($output, $content);
return self::appendCode($output, "<?php }\n}\n?>");
}
/**
* Create code frame of compiled template function
*
* @param \Smarty_Internal_Template $_template
* @param string $content
*
* @return string
*/
public static function createFunctionFrame(Smarty_Internal_Template $_template, $content = '')
{
if (!isset($_template->properties['unifunc'])) {
$_template->properties['unifunc'] = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
}
$output = "<?php\n";
$output .= "/*%%SmartyHeaderCode:{$_template->properties['nocache_hash']}%%*/\n";
$output .= "if (\$_valid && !is_callable('{$_template->properties['unifunc']}')) {\n";
$output .= "function {$_template->properties['unifunc']} (\$_smarty_tpl) {\n";
$output .= "?>\n" . $content;
$output .= "<?php\n";
$output .= "/*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%*/\n";
$output .= "}\n}\n?>";
return $output;
}
/**
* Append code segments and remove unneeded ?> <?php transitions
*
* @param string $left
* @param string $right
*
* @return string
*/
public static function appendCode($left, $right)
{
if (preg_match('/\s*\?>$/', $left) && preg_match('/^<\?php\s+/', $right)) {
$left = preg_replace('/\s*\?>$/', "\n", $left);
$left .= preg_replace('/^<\?php\s+/', '', $right);
} else {
$left .= $right;
}
return $left;
}
}

View File

@ -0,0 +1,160 @@
<?php
/**
* @package Smarty
* @subpackage PluginsInternal
*/
class Smarty_Internal_Extension_Config
{
/**
* @param $obj
* @param $config_file
* @param null $sections
* @param string $scope
*/
static function configLoad($obj, $config_file, $sections = null, $scope = 'local')
{
$smarty = isset($obj->smarty) ? $obj->smarty : $obj;
$confObj = new $smarty->template_class($config_file, $smarty, $obj);
$confObj->caching = Smarty::CACHING_OFF;
$confObj->source = Smarty_Template_Config::load($confObj);
$confObj->source->config_sections = $sections;
$confObj->source->scope = $scope;
$confObj->compiled = Smarty_Template_Compiled::load($confObj);
if ($confObj->smarty->debugging) {
Smarty_Internal_Debug::start_render($confObj);
}
$confObj->compiled->render($confObj);
if ($confObj->smarty->debugging) {
Smarty_Internal_Debug::end_render($confObj);
}
if ($obj instanceof Smarty_Internal_Template) {
$obj->properties['file_dependency'][$confObj->source->uid] = array($confObj->source->filepath, $confObj->source->timestamp, $confObj->source->type);
}
}
/**
* load config variables
*
* @param mixed $sections array of section names, single section or null
* @param string $scope global,parent or local
*
* @throws Exception
*/
static function loadConfigVars($_template, $_config_vars)
{
$scope = $_template->source->scope;
// pointer to scope (local scope is parent of template object
$scope_ptr = $_template->parent;
if ($scope == 'parent') {
if (isset($_template->parent->parent)) {
$scope_ptr = $_template->parent->parent;
}
} elseif ($scope == 'root' || $scope == 'global') {
while (isset($scope_ptr->parent)) {
$scope_ptr = $scope_ptr->parent;
}
}
// copy global config vars
foreach ($_config_vars['vars'] as $variable => $value) {
if ($_template->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) {
$scope_ptr->config_vars[$variable] = $value;
} else {
$scope_ptr->config_vars[$variable] = array_merge((array) $scope_ptr->config_vars[$variable], (array) $value);
}
}
// scan sections
$sections = $_template->source->config_sections;
if (!empty($sections)) {
foreach ((array) $sections as $_template_section) {
if (isset($_config_vars['sections'][$_template_section])) {
foreach ($_config_vars['sections'][$_template_section]['vars'] as $variable => $value) {
if ($_template->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) {
$scope_ptr->config_vars[$variable] = $value;
} else {
$scope_ptr->config_vars[$variable] = array_merge((array) $scope_ptr->config_vars[$variable], (array) $value);
}
}
}
}
}
}
/**
* Returns a single or all config variables
*
* @param string $varname variable name or null
* @param bool $search_parents
*
* @return string variable value or or array of variables
*/
static function getConfigVars($obj, $varname = null, $search_parents = true)
{
$_ptr = $obj;
$var_array = array();
while ($_ptr !== null) {
if (isset($varname)) {
if (isset($_ptr->config_vars[$varname])) {
return $_ptr->config_vars[$varname];
}
} else {
$var_array = array_merge($_ptr->config_vars, $var_array);
}
// not found, try at parent
if ($search_parents) {
$_ptr = $_ptr->parent;
} else {
$_ptr = null;
}
}
if (isset($varname)) {
return '';
} else {
return $var_array;
}
}
/**
* gets a config variable
*
* @param string $variable the name of the config variable
* @param bool $error_enable
*
* @return mixed the value of the config variable
*/
static function getConfigVariable($obj, $variable, $error_enable = true)
{
$_ptr = $obj;
while ($_ptr !== null) {
if (isset($_ptr->config_vars[$variable])) {
// found it, return it
return $_ptr->config_vars[$variable];
}
// not found, try at parent
$_ptr = $_ptr->parent;
}
if ($obj->error_unassigned && $error_enable) {
// force a notice
$x = $$variable;
}
return null;
}
/**
* remove a single or all config variables
*
* @param string $name variable name or null
*
* @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining
*/
static function clearConfig($obj, $name = null)
{
if (isset($name)) {
unset($obj->config_vars[$name]);
} else {
$obj->config_vars = array();
}
return $obj;
}
}

View File

@ -0,0 +1,85 @@
<?php
/**
* Smarty Resource Extension
*
* @package Smarty
* @subpackage TemplateResources
* @author Uwe Tews
*/
/**
* Smarty Resource Extension
* Default template and config file handling
*
* @package Smarty
* @subpackage TemplateResources
*/
class Smarty_Internal_Extension_DefaultTemplateHandler
{
/**
* get default content from template of config resource handler
*
* @param Smarty_Internal_Template $_template
* @param Smarty_Internal_Template_Source $source
* @param Smarty_Resource $resObj
*/
static function _getDefault(Smarty_Internal_Template $_template, &$source, &$resObj)
{
if ($source->isConfig) {
$default_handler = $_template->smarty->default_config_handler_func;
} else {
$default_handler = $_template->smarty->default_template_handler_func;
}
$_content = $_timestamp = null;
$_return = call_user_func_array($default_handler,
array($source->type, $source->name, &$_content, &$_timestamp, $source->smarty));
if (is_string($_return)) {
$source->exists = is_file($_return);
if ($source->exists) {
$source->timestamp = filemtime($_return);
}
$source->filepath = $_return;
} elseif ($_return === true) {
$source->content = $_content;
$source->timestamp = $_timestamp;
$source->exists = true;
$source->recompiled = true;
$source->filepath = false;
}
}
/**
* register template default handler
*
* @param Smarty $smarty
* @param mixed $callback
*
* @throws SmartyException
*/
static function registerDefaultTemplateHandler(Smarty $smarty, $callback)
{
if (is_callable($callback)) {
$smarty->default_template_handler_func = $callback;
} else {
throw new SmartyException("Default template handler not callable");
}
}
/**
* register config default handler
*
* @param Smarty $smarty
* @param mixed $callback
*
* @throws SmartyException
*/
static function registerDefaultConfigHandler(Smarty $smarty, $callback)
{
if (is_callable($callback)) {
$smarty->default_config_handler_func = $callback;
} else {
throw new SmartyException("Default config handler not callable");
}
}
}

View File

@ -8,7 +8,10 @@
*/
/**
* This class does call function defined with the {function} tag
* This class does handles template functions defined with the {function} tag missing in cache file.
* It can happen when the template function was called with the nocache option or within a nocache section.
* The template function will be loaded from it's compiled template file, executed and added to the cache file
* for later use.
*
* @package Smarty
* @subpackage PluginsInternal
@ -20,33 +23,49 @@ class Smarty_Internal_Function_Call_Handler
* It does create a PHP function at the first call
*
* @param string $_name template function name
* @param Smarty_Internal_Template $_template template object
* @param Smarty_Internal_Template $_smarty_tpl
* @param string $_function PHP function name
* @param array $_params Smarty variables passed as call parameter
* @param string $_hash nocache hash value
* @param bool $_nocache nocache flag
*
* @return bool
*/
public static function call($_name, Smarty_Internal_Template $_template, $_params, $_hash, $_nocache)
public static function call($_name, Smarty_Internal_Template $_smarty_tpl, $_function, $_params, $_nocache)
{
if ($_nocache) {
$_function = "smarty_template_function_{$_name}_nocache";
} else {
$_function = "smarty_template_function_{$_hash}_{$_name}";
}
if (!is_callable($_function)) {
$_code = "function {$_function}(\$_smarty_tpl,\$params) {
\$saved_tpl_vars = \$_smarty_tpl->tpl_vars;
foreach (\$_smarty_tpl->smarty->template_functions['{$_name}']['parameter'] as \$key => \$value) {\$_smarty_tpl->tpl_vars[\$key] = new Smarty_variable(\$value);};
foreach (\$params as \$key => \$value) {\$_smarty_tpl->tpl_vars[\$key] = new Smarty_variable(\$value);}?>";
if ($_nocache) {
$_code .= preg_replace(array("!<\?php echo \\'/\*%%SmartyNocache:{$_template->smarty->template_functions[$_name]['nocache_hash']}%%\*/|/\*/%%SmartyNocache:{$_template->smarty->template_functions[$_name]['nocache_hash']}%%\*/\\';\?>!",
"!\\\'!"), array('', "'"), $_template->smarty->template_functions[$_name]['compiled']);
$_template->smarty->template_functions[$_name]['called_nocache'] = true;
} else {
$_code .= preg_replace("/{$_template->smarty->template_functions[$_name]['nocache_hash']}/", $_template->properties['nocache_hash'], $_template->smarty->template_functions[$_name]['compiled']);
$funcParam = $_smarty_tpl->properties['tpl_function'][$_name];
if (is_file($funcParam['compiled_filepath'])) {
// read compiled file
$code = file_get_contents($funcParam['compiled_filepath']);
// grab template function
if (preg_match("/\/\* {$_function} \*\/([\S\s]*?)\/\*\/ {$_function} \*\//", $code, $match)) {
// grab source info from file dependency
preg_match("/\s*'{$funcParam['uid']}'([\S\s]*?)\),/", $code, $match1);
unset($code);
$output = '';
// make PHP function known
eval($match[0]);
if (function_exists($_function)) {
// search cache file template
$tplPtr = $_smarty_tpl;
while (!isset($tplPtr->cached) && isset($tplPtr->parent)) {
$tplPtr = $tplPtr->parent;
}
// add template function code to cache file
if (isset($tplPtr->cached)) {
$cache = $tplPtr->cached;
$content = $cache->read($tplPtr);
if ($content) {
// check if we must update file dependency
if (!preg_match("/'{$funcParam['uid']}'([\S\s]*?)'nocache_hash'/", $content, $match2)) {
$content = preg_replace("/('file_dependency'([\S\s]*?)\()/", "\\1{$match1[0]}", $content);
}
$cache->write($tplPtr, $content . "<?php " . $match[0] . "?>\n");
}
}
return true;
}
}
$_code .= "<?php \$_smarty_tpl->tpl_vars = \$saved_tpl_vars;}";
eval($_code);
}
$_function($_template, $_params);
return false;
}
}

View File

@ -14,14 +14,16 @@
* @subpackage Compiler
* @ignore
*/
abstract class _smarty_parsetree
abstract class Smarty_Internal_ParseTree
{
/**
* Parser object
*
* @var object
*/
public $parser;
/**
* Buffer content
*
@ -44,318 +46,4 @@ abstract class _smarty_parsetree
abstract public function to_smarty_php();
}
/**
* A complete smarty tag.
*
* @package Smarty
* @subpackage Compiler
* @ignore
*/
class _smarty_tag extends _smarty_parsetree
{
/**
* Saved block nesting level
*
* @var int
*/
public $saved_block_nesting;
/**
* Create parse tree buffer for Smarty tag
*
* @param object $parser parser object
* @param string $data content
*/
public function __construct($parser, $data)
{
$this->parser = $parser;
$this->data = $data;
$this->saved_block_nesting = $parser->block_nesting_level;
}
/**
* Return buffer content
*
* @return string content
*/
public function to_smarty_php()
{
return $this->data;
}
/**
* Return complied code that loads the evaluated output of buffer content into a temporary variable
*
* @return string template code
*/
public function assign_to_var()
{
$var = sprintf('$_tmp%d', ++Smarty_Internal_Templateparser::$prefix_number);
$this->parser->compiler->prefix_code[] = sprintf("<?php ob_start();\n%s\n%s=ob_get_clean();?>", preg_replace(array('/^\s*<\?php\s+/','/\s*\?>\s*$/'), '', $this->data), $var);
return $var;
}
}
/**
* Code fragment inside a tag.
*
* @package Smarty
* @subpackage Compiler
* @ignore
*/
class _smarty_code extends _smarty_parsetree
{
/**
* Create parse tree buffer for code fragment
*
* @param object $parser parser object
* @param string $data content
*/
public function __construct($parser, $data)
{
$this->parser = $parser;
$this->data = $data;
}
/**
* Return buffer content in parentheses
*
* @return string content
*/
public function to_smarty_php()
{
return sprintf("(%s)", $this->data);
}
}
/**
* Double quoted string inside a tag.
*
* @package Smarty
* @subpackage Compiler
* @ignore
*/
class _smarty_doublequoted extends _smarty_parsetree
{
/**
* Create parse tree buffer for double quoted string subtrees
*
* @param object $parser parser object
* @param _smarty_parsetree $subtree parsetree buffer
*/
public function __construct($parser, _smarty_parsetree $subtree)
{
$this->parser = $parser;
$this->subtrees[] = $subtree;
if ($subtree instanceof _smarty_tag) {
$this->parser->block_nesting_level = count($this->parser->compiler->_tag_stack);
}
}
/**
* Append buffer to subtree
*
* @param _smarty_parsetree $subtree parsetree buffer
*/
public function append_subtree(_smarty_parsetree $subtree)
{
$last_subtree = count($this->subtrees) - 1;
if ($last_subtree >= 0 && $this->subtrees[$last_subtree] instanceof _smarty_tag && $this->subtrees[$last_subtree]->saved_block_nesting < $this->parser->block_nesting_level) {
if ($subtree instanceof _smarty_code) {
$this->subtrees[$last_subtree]->data .= '<?php echo ' . $subtree->data . ';?>';
} elseif ($subtree instanceof _smarty_dq_content) {
$this->subtrees[$last_subtree]->data .= '<?php echo "' . $subtree->data . '";?>';
} else {
$this->subtrees[$last_subtree]->data .= $subtree->data;
}
} else {
$this->subtrees[] = $subtree;
}
if ($subtree instanceof _smarty_tag) {
$this->parser->block_nesting_level = count($this->parser->compiler->_tag_stack);
}
}
/**
* Merge subtree buffer content together
*
* @return string compiled template code
*/
public function to_smarty_php()
{
$code = '';
foreach ($this->subtrees as $subtree) {
if ($code !== "") {
$code .= ".";
}
if ($subtree instanceof _smarty_tag) {
$more_php = $subtree->assign_to_var();
} else {
$more_php = $subtree->to_smarty_php();
}
$code .= $more_php;
if (!$subtree instanceof _smarty_dq_content) {
$this->parser->compiler->has_variable_string = true;
}
}
return $code;
}
}
/**
* Raw chars as part of a double quoted string.
*
* @package Smarty
* @subpackage Compiler
* @ignore
*/
class _smarty_dq_content extends _smarty_parsetree
{
/**
* Create parse tree buffer with string content
*
* @param object $parser parser object
* @param string $data string section
*/
public function __construct($parser, $data)
{
$this->parser = $parser;
$this->data = $data;
}
/**
* Return content as double quoted string
*
* @return string doubled quoted string
*/
public function to_smarty_php()
{
return '"' . $this->data . '"';
}
}
/**
* Template element
*
* @package Smarty
* @subpackage Compiler
* @ignore
*/
class _smarty_template_buffer extends _smarty_parsetree
{
/**
* Array of template elements
*
* @var array
*/
public $subtrees = Array();
/**
* Create root of parse tree for template elements
*
* @param object $parser parse object
*/
public function __construct($parser)
{
$this->parser = $parser;
}
/**
* Append buffer to subtree
*
* @param _smarty_parsetree $subtree
*/
public function append_subtree(_smarty_parsetree $subtree)
{
if ($subtree->data !== '') {
$this->subtrees[] = $subtree;
}
}
/**
* Sanitize and merge subtree buffers together
*
* @return string template code content
*/
public function to_smarty_php()
{
$code = '';
for ($key = 0, $cnt = count($this->subtrees); $key < $cnt; $key ++) {
if ($this->subtrees[$key] instanceof _smarty_text) {
$subtree = $this->subtrees[$key]->to_smarty_php();
while ($key + 1 < $cnt && ($this->subtrees[$key+1] instanceof _smarty_text || $this->subtrees[$key +1]->data == '')) {
$key++;
if ($this->subtrees[$key]->data == '') {
continue;
}
$subtree .= $this->subtrees[$key]->to_smarty_php();
}
if ($subtree == '') {
continue;
}
$code .= preg_replace('/(<%|%>|<\?php|<\?|\?>|<\/?script)/', "<?php echo '\$1'; ?>\n", $subtree);
continue;
}
if ($this->subtrees[$key] instanceof _smarty_tag) {
$subtree = $this->subtrees[$key]->to_smarty_php();
while ($key + 1 < $cnt && ($this->subtrees[$key+1] instanceof _smarty_tag || $this->subtrees[$key +1]->data == '')) {
$key++;
if ($this->subtrees[$key]->data == '') {
continue;
}
$newCode = $this->subtrees[$key]->to_smarty_php();
if ((preg_match('/^\s*<\?php\s+/', $newCode) && preg_match('/\s*\?>\s*$/', $subtree))) {
$subtree = preg_replace('/\s*\?>\s*$/', "\n", $subtree);
$subtree .= preg_replace('/^\s*<\?php\s+/', '', $newCode);
} else {
$subtree .= $newCode;
}
}
if ($subtree == '') {
continue;
}
$code .= $subtree;
continue;
}
$code .= $this->subtrees[$key]->to_smarty_php();
}
return $code;
}
}
/**
* template text
*
* @package Smarty
* @subpackage Compiler
* @ignore
*/
class _smarty_text extends _smarty_parsetree
{
/**
* Create template text buffer
*
* @param object $parser parser object
* @param string $data text
*/
public function __construct($parser, $data)
{
$this->parser = $parser;
$this->data = $data;
}
/**
* Return buffer content
*
* @return strint text
*/
public function to_smarty_php()
{
return $this->data;
}
}

View File

@ -0,0 +1,42 @@
<?php
/**
* Smarty Internal Plugin Templateparser Parse Tree
* These are classes to build parse trees in the template parser
*
* @package Smarty
* @subpackage Compiler
* @author Thue Kristensen
* @author Uwe Tews
*/
/**
* Code fragment inside a tag .
*
* @package Smarty
* @subpackage Compiler
* @ignore
*/
class Smarty_Internal_ParseTree_Code extends Smarty_Internal_ParseTree
{
/**
* Create parse tree buffer for code fragment
*
* @param object $parser parser object
* @param string $data content
*/
public function __construct($parser, $data)
{
$this->parser = $parser;
$this->data = $data;
}
/**
* Return buffer content in parentheses
*
* @return string content
*/
public function to_smarty_php()
{
return sprintf("(%s)", $this->data);
}
}

View File

@ -0,0 +1,86 @@
<?php
/**
* Double quoted string inside a tag.
*
* @package Smarty
* @subpackage Compiler
* @ignore
*/
/**
* Double quoted string inside a tag.
*
* @package Smarty
* @subpackage Compiler
* @ignore
*/
class Smarty_Internal_ParseTree_Dq extends Smarty_Internal_ParseTree
{
/**
* Create parse tree buffer for double quoted string subtrees
*
* @param object $parser parser object
* @param Smarty_Internal_ParseTree $subtree parse tree buffer
*/
public function __construct($parser, Smarty_Internal_ParseTree $subtree)
{
$this->parser = $parser;
$this->subtrees[] = $subtree;
if ($subtree instanceof Smarty_Internal_ParseTree_Tag) {
$this->parser->block_nesting_level = count($this->parser->compiler->_tag_stack);
}
}
/**
* Append buffer to subtree
*
* @param Smarty_Internal_ParseTree $subtree parse tree buffer
*/
public function append_subtree(Smarty_Internal_ParseTree $subtree)
{
$last_subtree = count($this->subtrees) - 1;
if ($last_subtree >= 0 && $this->subtrees[$last_subtree] instanceof Smarty_Internal_ParseTree_Tag && $this->subtrees[$last_subtree]->saved_block_nesting < $this->parser->block_nesting_level) {
if ($subtree instanceof Smarty_Internal_ParseTree_Code) {
$this->subtrees[$last_subtree]->data = $this->parser->compiler->appendCode($this->subtrees[$last_subtree]->data, '<?php echo ' . $subtree->data . ';?>');
} elseif ($subtree instanceof Smarty_Internal_ParseTree_DqContent) {
$this->subtrees[$last_subtree]->data = $this->parser->compiler->appendCode($this->subtrees[$last_subtree]->data, '<?php echo "' . $subtree->data . '";?>');
} else {
$this->subtrees[$last_subtree]->data = $this->parser->compiler->appendCode($this->subtrees[$last_subtree]->data, $subtree->data);
}
} else {
$this->subtrees[] = $subtree;
}
if ($subtree instanceof Smarty_Internal_ParseTree_Tag) {
$this->parser->block_nesting_level = count($this->parser->compiler->_tag_stack);
}
}
/**
* Merge subtree buffer content together
*
* @return string compiled template code
*/
public function to_smarty_php()
{
$code = '';
foreach ($this->subtrees as $subtree) {
if ($code !== "") {
$code .= ".";
}
if ($subtree instanceof Smarty_Internal_ParseTree_Tag) {
$more_php = $subtree->assign_to_var();
} else {
$more_php = $subtree->to_smarty_php();
}
$code .= $more_php;
if (!$subtree instanceof Smarty_Internal_ParseTree_DqContent) {
$this->parser->compiler->has_variable_string = true;
}
}
return $code;
}
}

View File

@ -0,0 +1,42 @@
<?php
/**
* Smarty Internal Plugin Templateparser Parse Tree
* These are classes to build parse tree in the template parser
*
* @package Smarty
* @subpackage Compiler
* @author Thue Kristensen
* @author Uwe Tews
*/
/**
* Raw chars as part of a double quoted string.
*
* @package Smarty
* @subpackage Compiler
* @ignore
*/
class Smarty_Internal_ParseTree_DqContent extends Smarty_Internal_ParseTree
{
/**
* Create parse tree buffer with string content
*
* @param object $parser parser object
* @param string $data string section
*/
public function __construct($parser, $data)
{
$this->parser = $parser;
$this->data = $data;
}
/**
* Return content as double quoted string
*
* @return string doubled quoted string
*/
public function to_smarty_php()
{
return '"' . $this->data . '"';
}
}

View File

@ -0,0 +1,66 @@
<?php
/**
* Smarty Internal Plugin Templateparser Parse Tree
* These are classes to build parse tree in the template parser
*
* @package Smarty
* @subpackage Compiler
* @author Thue Kristensen
* @author Uwe Tews
*/
/**
* A complete smarty tag.
*
* @package Smarty
* @subpackage Compiler
* @ignore
*/
class Smarty_Internal_ParseTree_Tag extends Smarty_Internal_ParseTree
{
/**
* Saved block nesting level
*
* @var int
*/
public $saved_block_nesting;
/**
* Create parse tree buffer for Smarty tag
*
* @param object $parser parser object
* @param string $data content
*/
public function __construct($parser, $data)
{
$this->parser = $parser;
$this->data = $data;
$this->saved_block_nesting = $parser->block_nesting_level;
}
/**
* Return buffer content
*
* @return string content
*/
public function to_smarty_php()
{
return $this->data;
}
/**
* Return complied code that loads the evaluated output of buffer content into a temporary variable
*
* @return string template code
*/
public function assign_to_var()
{
$var = sprintf('$_tmp%d', ++ Smarty_Internal_Templateparser::$prefix_number);
$tmp = $this->parser->compiler->appendCode('<?php ob_start();?>', $this->data);
$tmp = $this->parser->compiler->appendCode($tmp, "<?php {$var}=ob_get_clean();?>");
$this->parser->compiler->prefix_code[] = sprintf("%s", $tmp);
return $var;
}
}

View File

@ -0,0 +1,98 @@
<?php
/**
* Smarty Internal Plugin Templateparser Parse Tree
* These are classes to build parse tree in the template parser
*
* @package Smarty
* @subpackage Compiler
* @author Thue Kristensen
* @author Uwe Tews
*/
/**
* Template element
*
* @package Smarty
* @subpackage Compiler
* @ignore
*/
class Smarty_Internal_ParseTree_Template extends Smarty_Internal_ParseTree
{
/**
* Array of template elements
*
* @var array
*/
public $subtrees = Array();
/**
* Create root of parse tree for template elements
*
* @param object $parser parse object
*/
public function __construct($parser)
{
$this->parser = $parser;
}
/**
* Append buffer to subtree
*
* @param Smarty_Internal_ParseTree $subtree
*/
public function append_subtree(Smarty_Internal_ParseTree $subtree)
{
if (!empty($subtree->subtrees)) {
$this->subtrees = array_merge($this->subtrees, $subtree->subtrees);
} else {
if ($subtree->data !== '') {
$this->subtrees[] = $subtree;
}
}
}
/**
* Sanitize and merge subtree buffers together
*
* @return string template code content
*/
public function to_smarty_php()
{
$code = '';
for ($key = 0, $cnt = count($this->subtrees); $key < $cnt; $key ++) {
if ($this->subtrees[$key] instanceof Smarty_Internal_ParseTree_Text) {
$subtree = $this->subtrees[$key]->to_smarty_php();
while ($key + 1 < $cnt && ($this->subtrees[$key + 1] instanceof Smarty_Internal_ParseTree_Text || $this->subtrees[$key + 1]->data == '')) {
$key ++;
if ($this->subtrees[$key]->data == '') {
continue;
}
$subtree .= $this->subtrees[$key]->to_smarty_php();
}
if ($subtree == '') {
continue;
}
$code .= preg_replace('/((<%)|(%>)|(<\?php)|(<\?)|(\?>)|(<\/?script))/', "<?php echo '\$1'; ?>\n", $subtree);
continue;
}
if ($this->subtrees[$key] instanceof Smarty_Internal_ParseTree_Tag) {
$subtree = $this->subtrees[$key]->to_smarty_php();
while ($key + 1 < $cnt && ($this->subtrees[$key + 1] instanceof Smarty_Internal_ParseTree_Tag || $this->subtrees[$key + 1]->data == '')) {
$key ++;
if ($this->subtrees[$key]->data == '') {
continue;
}
$subtree = $this->parser->compiler->appendCode($subtree, $this->subtrees[$key]->to_smarty_php());
}
if ($subtree == '') {
continue;
}
$code .= $subtree;
continue;
}
$code .= $this->subtrees[$key]->to_smarty_php();
}
return $code;
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* Smarty Internal Plugin Templateparser Parse Tree
* These are classes to build parse tree in the template parser
*
* @package Smarty
* @subpackage Compiler
* @author Thue Kristensen
* @author Uwe Tews
* *
* template text
* @package Smarty
* @subpackage Compiler
* @ignore
*/
class Smarty_Internal_ParseTree_Text extends Smarty_Internal_ParseTree
{
/**
* Create template text buffer
*
* @param object $parser parser object
* @param string $data text
*/
public function __construct($parser, $data)
{
$this->parser = $parser;
$this->data = $data;
}
/**
* Return buffer content
*
* @return string text
*/
public function to_smarty_php()
{
return $this->data;
}
}

View File

@ -73,11 +73,11 @@ class Smarty_Internal_Resource_Eval extends Smarty_Resource_Recompiled
*
* @param Smarty $smarty Smarty instance
* @param string $resource_name resource_name to make unique
* @param boolean $is_config flag for config resource
* @param boolean $isConfig flag for config resource
*
* @return string unique resource name
*/
protected function buildUniqueResourceName(Smarty $smarty, $resource_name, $is_config = false)
public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false)
{
return get_class($this) . '#' . $this->decode($resource_name);
}
@ -89,7 +89,7 @@ class Smarty_Internal_Resource_Eval extends Smarty_Resource_Recompiled
*
* @return string resource's basename
*/
protected function getBasename(Smarty_Template_Source $source)
public function getBasename(Smarty_Template_Source $source)
{
return '';
}

View File

@ -34,7 +34,7 @@ class Smarty_Internal_Resource_Extends extends Smarty_Resource
*/
public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null)
{
$uid = '';
$uid = sha1(getcwd());
$sources = array();
$components = explode('|', $source->name);
$exists = true;

View File

@ -17,6 +17,137 @@
*/
class Smarty_Internal_Resource_File extends Smarty_Resource
{
private $dsMap = array('/' => array(array('\\', '/./'), '/.'), '\\' => array(array('/', '\\.\\'), '\\.'));
/**
* build template filepath by traversing the template_dir array
*
* @param Smarty_Template_Source $source source object
* @param Smarty_Internal_Template $_template template object
*
* @return string fully qualified filepath
* @throws SmartyException
*/
protected function buildFilepath(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null)
{
$file = $source->name;
preg_match('#^(?P<absolute>[\\\/]|[a-zA-Z]:[\\\/])|(\[(?P<index>[^\]]+)\])|(?P<rel>\.[\\\/])#', $file, $fileMatch);
// save basename
if (!empty($fileMatch['absolute'])) {
$file = $this->normalizePath($file);
return is_file($file) ? $file : false;
}
// go relative to a given template?
if (!empty($fileMatch['rel']) && $_template && $_template->parent instanceof Smarty_Internal_Template) {
if ($_template->parent->source->type != 'file' && $_template->parent->source->type != 'extends' && !$_template->parent->allow_relative_path) {
throw new SmartyException("Template '{$file}' cannot be relative to template of resource type '{$_template->parent->source->type}'");
}
$path = dirname($_template->parent->source->filepath) . DS . $file;
// normalize path
$path = $this->normalizePath($path);
// files relative to a template only get one shot
return is_file($path) ? $path : false;
}
if ($source->isConfig) {
$_directories = $source->smarty->getConfigDir();
} else {
$_directories = $source->smarty->getTemplateDir();
}
// template_dir index?
if (!empty($fileMatch['index'])) {
$index = $fileMatch['index'];
$_directory = null;
// try string indexes
if (isset($_directories[$index])) {
$_directory = $_directories[$index];
} elseif (is_numeric($index)) {
// try numeric index
$index = (int) $index;
if (isset($_directories[$index])) {
$_directory = $_directories[$index];
} else {
// try at location index
$keys = array_keys($_directories);
$_directory = $_directories[$keys[$index]];
}
}
if ($_directory) {
preg_match('#\](.+)$#', $file, $fileMatch);
$path = $_directory . $fileMatch[1];
$path = $this->normalizePath($path);
if (is_file($path)) {
return $path;
}
} else {
// index not found
return false;
}
}
// relative file name?
foreach ($_directories as $_directory) {
$_filepath = $_directory . $file;
$path = $this->normalizePath($_filepath);
if (is_file($path)) {
return $path;
}
if ($source->smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_directory)) {
// try PHP include_path
if (function_exists('stream_resolve_include_path')) {
$_filepath = stream_resolve_include_path($_filepath);
} else {
$_filepath = Smarty_Internal_Get_Include_Path::getIncludePath($_filepath);
}
if ($_filepath !== false) {
$path = $this->normalizePath($_filepath);
if (is_file($path)) {
return $path;
}
}
}
}
// Could be relative to cwd
$path = $this->normalizePath(getcwd() . DS . $file);
return is_file($path) ? $path : false;
}
/**
* Normalize path
* - remove /./ and /../
* - make it absolute
*
* @param string $path file path
*
* @return string
*/
public function normalizePath($path)
{
if ($path[0] == '.') {
$path = getcwd() . DS . $path;
}
$path = str_replace($this->dsMap[DS][0], DS, $path);
while (strrpos($path, $this->dsMap[DS][1]) !== false) {
$path = preg_replace('#([\\\/][.][\\\/])|([\\\/][^\\\/]+[\\\/][.][.][\\\/])#', DS, $path);
}
return $path;
}
/**
* test is file exists and save timestamp
*
* @param Smarty_Template_Source $source source object
* @param string $file file name
*
* @return bool true if file exists
*/
protected function fileExists(Smarty_Template_Source $source, $file)
{
$source->timestamp = is_file($file) ? @filemtime($file) : false;
return $source->exists = !!$source->timestamp;
}
/**
* populate Source Object with meta data from Resource
*
@ -31,12 +162,14 @@ class Smarty_Internal_Resource_File extends Smarty_Resource
if (is_object($source->smarty->security_policy)) {
$source->smarty->security_policy->isTrustedResourceDir($source->filepath);
}
$source->uid = sha1(realpath($source->filepath));
$source->exists = true;
$source->uid = sha1($source->filepath);
if ($source->smarty->compile_check && !isset($source->timestamp)) {
$source->timestamp = @filemtime($source->filepath);
$source->exists = !!$source->timestamp;
}
} else {
$source->timestamp = false;
$source->exists = false;
}
}
@ -47,8 +180,10 @@ class Smarty_Internal_Resource_File extends Smarty_Resource
*/
public function populateTimestamp(Smarty_Template_Source $source)
{
$source->timestamp = @filemtime($source->filepath);
$source->exists = !!$source->timestamp;
$source->timestamp = $source->exists = is_file($source->filepath);
if ($source->exists) {
$source->timestamp = @filemtime($source->filepath);
}
}
/**
@ -79,11 +214,6 @@ class Smarty_Internal_Resource_File extends Smarty_Resource
*/
public function getBasename(Smarty_Template_Source $source)
{
$_file = $source->name;
if (($_pos = strpos($_file, ']')) !== false) {
$_file = substr($_file, $_pos + 1);
}
return basename($_file);
return basename($source->filepath);
}
}

View File

@ -9,8 +9,14 @@
* @author Uwe Tews
* @author Rodney Rehm
*/
class Smarty_Internal_Resource_PHP extends Smarty_Resource_Uncompiled
class Smarty_Internal_Resource_Php extends Smarty_Internal_Resource_File
{
/**
* Flag that it's an uncompiled resource
*
* @var bool
*/
public $uncompiled = true;
/**
* container for short_open_tag directive's value before executing PHP templates
*
@ -27,44 +33,6 @@ class Smarty_Internal_Resource_PHP extends Smarty_Resource_Uncompiled
$this->short_open_tag = ini_get('short_open_tag');
}
/**
* populate Source Object with meta data from Resource
*
* @param Smarty_Template_Source $source source object
* @param Smarty_Internal_Template $_template template object
*
* @return void
*/
public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null)
{
$source->filepath = $this->buildFilepath($source, $_template);
if ($source->filepath !== false) {
if (is_object($source->smarty->security_policy)) {
$source->smarty->security_policy->isTrustedResourceDir($source->filepath);
}
$source->uid = sha1($source->filepath);
if ($source->smarty->compile_check) {
$source->timestamp = @filemtime($source->filepath);
$source->exists = !!$source->timestamp;
}
}
}
/**
* populate Source Object with timestamp and exists from Resource
*
* @param Smarty_Template_Source $source source object
*
* @return void
*/
public function populateTimestamp(Smarty_Template_Source $source)
{
$source->timestamp = @filemtime($source->filepath);
$source->exists = !!$source->timestamp;
}
/**
* Load template's source from file into current template object
*
@ -116,4 +84,17 @@ class Smarty_Internal_Resource_PHP extends Smarty_Resource_Uncompiled
include($source->filepath);
ini_set('short_open_tag', $this->short_open_tag);
}
/**
* populate compiled object with compiled filepath
*
* @param Smarty_Template_Compiled $compiled compiled object
* @param Smarty_Internal_Template $_template template object (is ignored)
*/
public function populateCompiledFilepath(Smarty_Template_Compiled $compiled, Smarty_Internal_Template $_template)
{
$compiled->filepath = false;
$compiled->timestamp = false;
$compiled->exists = false;
}
}

View File

@ -91,7 +91,7 @@ class Smarty_Internal_Resource_Registered extends Smarty_Resource
*
* @return string resource's basename
*/
protected function getBasename(Smarty_Template_Source $source)
public function getBasename(Smarty_Template_Source $source)
{
return basename($source->name);
}

View File

@ -70,11 +70,11 @@ class Smarty_Internal_Resource_Stream extends Smarty_Resource_Recompiled
*
* @param Smarty $smarty Smarty instance
* @param string $resource_name resource_name to make unique
* @param boolean $is_config flag for config resource
* @param boolean $isConfig flag for config resource
*
* @return string unique resource name
*/
protected function buildUniqueResourceName(Smarty $smarty, $resource_name, $is_config = false)
public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false)
{
return get_class($this) . '#' . $resource_name;
}

View File

@ -73,11 +73,11 @@ class Smarty_Internal_Resource_String extends Smarty_Resource
*
* @param Smarty $smarty Smarty instance
* @param string $resource_name resource_name to make unique
* @param boolean $is_config flag for config resource
* @param boolean $isConfig flag for config resource
*
* @return string unique resource name
*/
protected function buildUniqueResourceName(Smarty $smarty, $resource_name, $is_config = false)
public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false)
{
return get_class($this) . '#' . $this->decode($resource_name);
}
@ -90,7 +90,7 @@ class Smarty_Internal_Resource_String extends Smarty_Resource
*
* @return string resource's basename
*/
protected function getBasename(Smarty_Template_Source $source)
public function getBasename(Smarty_Template_Source $source)
{
return '';
}

View File

@ -11,7 +11,7 @@
/**
* @ignore
*/
include 'smarty_internal_parsetree.php';
//include 'smarty_internal_parsetree.php';
/**
* Class SmartyTemplateCompiler
@ -49,13 +49,6 @@ class Smarty_Internal_SmartyTemplateCompiler extends Smarty_Internal_TemplateCom
*/
public $parser;
/**
* Smarty object
*
* @var object
*/
public $smarty;
/**
* array of vars which can be compiled in local scope
*
@ -86,14 +79,17 @@ class Smarty_Internal_SmartyTemplateCompiler extends Smarty_Internal_TemplateCom
*
* @return bool true if compiling succeeded, false if it failed
*/
protected function doCompile($_content)
protected function doCompile($_content, $isTemplateSource = false)
{
/* here is where the compiling takes place. Smarty
tags in the templates are replaces with PHP code,
then written to compiled files. */
// init the lexer/parser to compile the template
$this->lex = new $this->lexer_class($_content, $this);
$this->lex = new $this->lexer_class(str_replace(array("\r\n", "\r"), "\n", $_content), $this);
$this->parser = new $this->parser_class($this->lex, $this);
if ($isTemplateSource) {
$this->parser->insertPhpCode("<?php\n\$_smarty_tpl->properties['nocache_hash'] = '{$this->nocache_hash}';\n?>\n");
}
if ($this->inheritance_child) {
// start state on child templates
$this->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBODY);

View File

@ -13,6 +13,7 @@
*
* @package Smarty
* @subpackage Template
*
* @property Smarty_Template_Source $source
* @property Smarty_Template_Compiled $compiled
* @property Smarty_Template_Cached $cached
@ -20,34 +21,24 @@
class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
{
/**
* cache_id
* Global smarty instance
*
* @var string
* @var Smarty
*/
public $cache_id = null;
/**
* $compile_id
* @var string
*/
public $compile_id = null;
/**
* caching enabled
*
* @var boolean
*/
public $caching = null;
/**
* cache lifetime in seconds
*
* @var integer
*/
public $cache_lifetime = null;
public $smarty = null;
/**
* Template resource
*
* @var string
*/
public $template_resource = null;
/**
* Saved template Id
*
* @var null|string
*/
public $templateId = null;
/**
* flag if compiled template is invalid and must be (re)compiled
*
@ -67,19 +58,14 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
*/
public $properties = array('file_dependency' => array(),
'nocache_hash' => '',
'function' => array());
'tpl_function' => array(),
);
/**
* required plugins
*
* @var array
*/
public $required_plugins = array('compiled' => array(), 'nocache' => array());
/**
* Global smarty instance
*
* @var Smarty
*/
public $smarty = null;
/**
* blocks for template inheritance
*
@ -114,7 +100,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
/**
* Create template data object
* Some of the global Smarty settings copied to template scope
* It load the required template resources and cacher plugins
* It load the required template resources and caching plugins
*
* @param string $template_resource template resource string
* @param Smarty $smarty Smarty instance
@ -126,7 +112,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
*/
public function __construct($template_resource, $smarty, $_parent = null, $_cache_id = null, $_compile_id = null, $_caching = null, $_cache_lifetime = null)
{
$this->smarty = & $smarty;
$this->smarty = &$smarty;
// Smarty parameter
$this->cache_id = $_cache_id === null ? $this->smarty->cache_id : $_cache_id;
$this->compile_id = $_compile_id === null ? $this->smarty->compile_id : $_compile_id;
@ -144,9 +130,267 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
}
}
/**
* fetches rendered template
*
* @throws Exception
* @throws SmartyException
* @return string rendered template output
*/
public function fetch()
{
return $this->render(true, false, false);
}
/**
* displays a Smarty template
*/
public function display()
{
$this->render(true, false, true);
}
/**
* render template
*
* @param bool $merge_tpl_vars if true parent template variables merged in to local scope
* @param bool $no_output_filter if true do not run output filter
* @param bool $display true: display, false: fetch null: subtemplate
*
* @throws Exception
* @throws SmartyException
* @return string rendered template output
*/
public function render($merge_tpl_vars = false, $no_output_filter = true, $display = null)
{
$parentIsTpl = $this->parent instanceof Smarty_Internal_Template;
if ($this->smarty->debugging) {
Smarty_Internal_Debug::start_template($this, $display);
}
$save_tpl_vars = null;
$save_config_vars = null;
// merge all variable scopes into template
if ($merge_tpl_vars) {
// save local variables
$save_tpl_vars = $this->tpl_vars;
$save_config_vars = $this->config_vars;
$ptr_array = array($this);
$ptr = $this;
while (isset($ptr->parent)) {
$ptr_array[] = $ptr = $ptr->parent;
}
$ptr_array = array_reverse($ptr_array);
$parent_ptr = reset($ptr_array);
$tpl_vars = $parent_ptr->tpl_vars;
$config_vars = $parent_ptr->config_vars;
while ($parent_ptr = next($ptr_array)) {
if (!empty($parent_ptr->tpl_vars)) {
$tpl_vars = array_merge($tpl_vars, $parent_ptr->tpl_vars);
}
if (!empty($parent_ptr->config_vars)) {
$config_vars = array_merge($config_vars, $parent_ptr->config_vars);
}
}
if (!empty(Smarty::$global_tpl_vars)) {
$tpl_vars = array_merge(Smarty::$global_tpl_vars, $tpl_vars);
}
$this->tpl_vars = $tpl_vars;
$this->config_vars = $config_vars;
}
// dummy local smarty variable
if (!isset($this->tpl_vars['smarty'])) {
$this->tpl_vars['smarty'] = new Smarty_Variable;
}
$_smarty_old_error_level = isset($this->smarty->error_reporting) ? error_reporting($this->smarty->error_reporting) : null;
// check URL debugging control
if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') {
Smarty_Internal_Debug::debugUrl($this);
}
if (!isset($this->source)) {
$this->loadSource();
}
// checks if template exists
if (!$this->source->exists) {
if ($parentIsTpl) {
$parent_resource = " in '{$this->parent->template_resource}'";
} else {
$parent_resource = '';
}
throw new SmartyException("Unable to load template {$this->source->type} '{$this->source->name}'{$parent_resource}");
}
// disable caching for evaluated code
if ($this->source->recompiled) {
$this->caching = false;
}
// read from cache or render
$isCacheTpl = $this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED;
if ($isCacheTpl) {
if (!isset($this->cached)) {
$this->loadCached();
}
$this->cached->isCached($this);
}
if (!($isCacheTpl) || !$this->cached->valid) {
if ($isCacheTpl) {
$this->properties['tpl_function'] = array();
}
// render template (not loaded and not in cache)
if ($this->smarty->debugging) {
Smarty_Internal_Debug::start_render($this);
}
if (!$this->source->uncompiled) {
// render compiled code
if (!isset($this->compiled)) {
$this->loadCompiled();
}
$content = $this->compiled->render($this);
} else {
$content = $this->source->renderUncompiled($this);
}
if (!$this->source->recompiled && empty($this->properties['file_dependency'][$this->source->uid])) {
$this->properties['file_dependency'][$this->source->uid] = array($this->source->filepath, $this->source->timestamp, $this->source->type);
}
if ($parentIsTpl) {
$this->parent->properties['file_dependency'] = array_merge($this->parent->properties['file_dependency'], $this->properties['file_dependency']);
//$this->parent->properties['tpl_function'] = array_merge($this->parent->properties['tpl_function'], $this->properties['tpl_function']);
}
if ($this->smarty->debugging) {
Smarty_Internal_Debug::end_render($this);
}
// write to cache when necessary
if (!$this->source->recompiled && $isCacheTpl) {
if ($this->smarty->debugging) {
Smarty_Internal_Debug::start_cache($this);
}
$this->cached->updateCache($this, $content, $no_output_filter);
$compile_check = $this->smarty->compile_check;
$this->smarty->compile_check = false;
if ($parentIsTpl) {
$this->properties['tpl_function'] = $this->parent->properties['tpl_function'];
}
if (!$this->cached->processed) {
$this->cached->process($this);
}
$this->smarty->compile_check = $compile_check;
$content = $this->getRenderedTemplateCode();
if ($this->smarty->debugging) {
Smarty_Internal_Debug::end_cache($this);
}
} else {
if (!empty($this->properties['nocache_hash']) && !empty($this->parent->properties['nocache_hash'])) {
// replace nocache_hash
$content = str_replace("{$this->properties['nocache_hash']}", $this->parent->properties['nocache_hash'], $content);
$this->parent->has_nocache_code = $this->parent->has_nocache_code || $this->has_nocache_code;
}
}
} else {
if ($this->smarty->debugging) {
Smarty_Internal_Debug::start_cache($this);
}
$content = $this->cached->render($this);
if ($this->smarty->debugging) {
Smarty_Internal_Debug::end_cache($this);
}
}
if ((!$this->caching || $this->has_nocache_code || $this->source->recompiled) && !$no_output_filter && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) {
$content = Smarty_Internal_Filter_Handler::runFilter('output', $content, $this);
}
if (isset($_smarty_old_error_level)) {
error_reporting($_smarty_old_error_level);
}
// display or fetch
if ($display) {
if ($this->caching && $this->smarty->cache_modified_check) {
$this->cached->cacheModifiedCheck($this, $content);
} else {
echo $content;
}
if ($this->smarty->debugging) {
Smarty_Internal_Debug::end_template($this);
}
// debug output
if ($this->smarty->debugging) {
Smarty_Internal_Debug::display_debug($this, true);
}
if ($merge_tpl_vars) {
// restore local variables
$this->tpl_vars = $save_tpl_vars;
$this->config_vars = $save_config_vars;
}
return '';
} else {
if ($merge_tpl_vars) {
// restore local variables
$this->tpl_vars = $save_tpl_vars;
$this->config_vars = $save_config_vars;
}
if ($this->smarty->debugging) {
Smarty_Internal_Debug::end_template($this);
}
if ($this->smarty->debugging == 2 and $display === false) {
if ($this->smarty->debugging) {
Smarty_Internal_Debug::display_debug($this, true);
}
}
if ($parentIsTpl) {
$this->parent->properties['tpl_function'] = array_merge($this->parent->properties['tpl_function'], $this->properties['tpl_function']);
foreach ($this->required_plugins as $code => $tmp1) {
foreach ($tmp1 as $name => $tmp) {
foreach ($tmp as $type => $data) {
$this->parent->required_plugins[$code][$name][$type] = $data;
}
}
}
}
// return cache content
return $content;
}
}
/**
* get rendered template content by calling compiled or cached template code
*
* @return string
* @throws Exception
*/
public function getRenderedTemplateCode()
{
$level = ob_get_level();
try {
ob_start();
if (empty($this->properties['unifunc']) || !is_callable($this->properties['unifunc'])) {
throw new SmartyException("Invalid compiled template for '{$this->template_resource}'");
}
if (isset($this->smarty->security_policy)) {
$this->smarty->security_policy->startTemplate($this);
}
array_unshift($this->_capture_stack, array());
//
// render compiled or saved template code
//
$this->properties['unifunc']($this);
// any unclosed {capture} tags ?
if (isset($this->_capture_stack[0][0])) {
$this->capture_error();
}
array_shift($this->_capture_stack);
if (isset($this->smarty->security_policy)) {
$this->smarty->security_policy->exitTemplate($this);
}
return ob_get_clean();
}
catch (Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
throw $e;
}
}
/**
* Returns if the current template must be compiled by the Smarty compiler
* It does compare the timestamps of template source and the compiled templates and checks the force compile configuration
* It does compare the timestamps of template source and the compiled templates and checks the force compile
* configuration
*
* @throws SmartyException
* @return boolean true if the template must be compiled
@ -175,51 +419,11 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
*/
public function compileTemplateSource()
{
if (!$this->source->recompiled) {
$this->properties['file_dependency'] = array();
if ($this->source->components) {
// for the extends resource the compiler will fill it
// uses real resource for file dependency
// $source = end($this->source->components);
// $this->properties['file_dependency'][$this->source->uid] = array($this->source->filepath, $this->source->timestamp, $source->type);
} else {
$this->properties['file_dependency'][$this->source->uid] = array($this->source->filepath, $this->source->timestamp, $this->source->type);
}
}
// compile locking
if ($this->smarty->compile_locking && !$this->source->recompiled) {
if ($saved_timestamp = $this->compiled->timestamp) {
touch($this->compiled->filepath);
}
}
// call compiler
try {
$code = $this->compiler->compileTemplate($this);
}
catch (Exception $e) {
// restore old timestamp in case of error
if ($this->smarty->compile_locking && !$this->source->recompiled && $saved_timestamp) {
touch($this->compiled->filepath, $saved_timestamp);
}
throw $e;
}
// compiling succeded
if (!$this->source->recompiled && $this->compiler->write_compiled_code) {
// write compiled template
$_filepath = $this->compiled->filepath;
if ($_filepath === false) {
throw new SmartyException('getCompiledFilepath() did not return a destination to save the compiled template to');
}
Smarty_Internal_Write_File::writeFile($_filepath, $code, $this->smarty);
$this->compiled->exists = true;
$this->compiled->isCompiled = true;
}
// release compiler object to free memory
unset($this->compiler);
return $this->compiled->compileTemplateSource($this);
}
/**
* Writes the cached template output
* Writes the content to cache resource
*
* @param string $content
*
@ -227,23 +431,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
*/
public function writeCachedContent($content)
{
if ($this->source->recompiled || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) {
// don't write cache file
return false;
}
$this->cached->timestamp = time();
$this->properties['cache_lifetime'] = $this->cache_lifetime;
$this->properties['unifunc'] = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
$content = $this->createTemplateCodeFrame($content, true);
/** @var Smarty_Internal_Template $_smarty_tpl
* used in evaluated code
*/
$_smarty_tpl = $this;
eval("?>" . $content);
$this->cached->valid = true;
$this->cached->processed = true;
return $this->cached->write($this, $content);
return $this->cached->writeCachedContent($this, $content);
}
/**
@ -261,47 +449,8 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
*/
public function getSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope)
{
// already in template cache?
if ($this->smarty->allow_ambiguous_resources) {
$_templateId = Smarty_Resource::getUniqueTemplateName($this, $template) . $cache_id . $compile_id;
} else {
$_templateId = $this->smarty->joined_template_dir . '#' . $template . $cache_id . $compile_id;
}
if (isset($_templateId[150])) {
$_templateId = sha1($_templateId);
}
if (isset($this->smarty->template_objects[$_templateId])) {
// clone cached template object because of possible recursive call
$tpl = clone $this->smarty->template_objects[$_templateId];
$tpl->parent = $this;
$tpl->caching = $caching;
$tpl->cache_lifetime = $cache_lifetime;
} else {
$tpl = new $this->smarty->template_class($template, $this->smarty, $this, $cache_id, $compile_id, $caching, $cache_lifetime);
}
// get variables from calling scope
if ($parent_scope == Smarty::SCOPE_LOCAL) {
$tpl->tpl_vars = $this->tpl_vars;
$tpl->tpl_vars['smarty'] = clone $this->tpl_vars['smarty'];
} elseif ($parent_scope == Smarty::SCOPE_PARENT) {
$tpl->tpl_vars = & $this->tpl_vars;
} elseif ($parent_scope == Smarty::SCOPE_GLOBAL) {
$tpl->tpl_vars = & Smarty::$global_tpl_vars;
} elseif (($scope_ptr = $this->getScopePointer($parent_scope)) == null) {
$tpl->tpl_vars = & $this->tpl_vars;
} else {
$tpl->tpl_vars = & $scope_ptr->tpl_vars;
}
$tpl->config_vars = $this->config_vars;
if (!empty($data)) {
// set up variable values
foreach ($data as $_key => $_val) {
$tpl->tpl_vars[$_key] = new Smarty_variable($_val);
}
}
return $tpl->fetch(null, null, null, null, false, false, true);
$tpl = $this->setupSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope);
return $tpl->render();
}
/**
@ -312,127 +461,124 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
* @param mixed $compile_id compile id to be used with this template
* @param integer $caching cache mode
* @param integer $cache_lifetime life time of cache data
* @param $data
* @param array $data passed parameter template variables
* @param int $parent_scope scope in which {include} should execute
* @param string $hash nocache hash code
*
* @returns string template content
* @returns object template object
*/
public function setupInlineSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $hash)
public function setupSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope)
{
$tpl = new $this->smarty->template_class($template, $this->smarty, $this, $cache_id, $compile_id, $caching, $cache_lifetime);
$tpl->properties['nocache_hash'] = $hash;
$_templateId = $this->getTemplateId($template, $cache_id, $compile_id);
// already in template cache?
if (isset($this->smarty->template_objects[$_templateId])) {
// clone cached template object because of possible recursive call
$tpl = clone $this->smarty->template_objects[$_templateId];
$tpl->parent = $this;
if ((bool) $tpl->caching !== (bool) $caching) {
unset($tpl->compiled);
}
$tpl->caching = $caching;
$tpl->cache_lifetime = $cache_lifetime;
} else {
$tpl = new $this->smarty->template_class($template, $this->smarty, $this, $cache_id, $compile_id, $caching, $cache_lifetime);
$tpl->templateId = $_templateId;
}
// get variables from calling scope
if ($parent_scope == Smarty::SCOPE_LOCAL) {
$tpl->tpl_vars = $this->tpl_vars;
$tpl->tpl_vars['smarty'] = clone $this->tpl_vars['smarty'];
} elseif ($parent_scope == Smarty::SCOPE_PARENT) {
$tpl->tpl_vars = & $this->tpl_vars;
$tpl->tpl_vars = &$this->tpl_vars;
} elseif ($parent_scope == Smarty::SCOPE_GLOBAL) {
$tpl->tpl_vars = & Smarty::$global_tpl_vars;
$tpl->tpl_vars = &Smarty::$global_tpl_vars;
} elseif (($scope_ptr = $this->getScopePointer($parent_scope)) == null) {
$tpl->tpl_vars = & $this->tpl_vars;
$tpl->tpl_vars = &$this->tpl_vars;
} else {
$tpl->tpl_vars = & $scope_ptr->tpl_vars;
$tpl->tpl_vars = &$scope_ptr->tpl_vars;
}
$tpl->config_vars = $this->config_vars;
if (!empty($data)) {
// set up variable values
foreach ($data as $_key => $_val) {
$tpl->tpl_vars[$_key] = new Smarty_variable($_val);
$tpl->tpl_vars[$_key] = new Smarty_Variable($_val);
}
}
$tpl->properties['tpl_function'] = $this->properties['tpl_function'];
return $tpl;
}
/**
* Create code frame for compiled and cached templates
* Template code runtime function to set up an inline subtemplate
*
* @param string $content optional template content
* @param bool $cache flag for cache file
* @param string $template the resource handle of the template file
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param integer $caching cache mode
* @param integer $cache_lifetime life time of cache data
* @param array $data passed parameter template variables
* @param int $parent_scope scope in which {include} should execute
* @param string $hash nocache hash code
* @param string $content_func name of content function
*
* @return string
* @returns object template content
*/
public function createTemplateCodeFrame($content = '', $cache = false)
public function getInlineSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $hash, $content_func)
{
$plugins_string = '';
// include code for plugins
if (!$cache) {
if (!empty($this->required_plugins['compiled'])) {
$plugins_string = '<?php ';
foreach ($this->required_plugins['compiled'] as $tmp) {
foreach ($tmp as $data) {
$file = addslashes($data['file']);
if (is_Array($data['function'])) {
$plugins_string .= "if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) include '{$file}';\n";
} else {
$plugins_string .= "if (!is_callable('{$data['function']}')) include '{$file}';\n";
}
}
}
$plugins_string .= '?>';
}
if (!empty($this->required_plugins['nocache'])) {
$this->has_nocache_code = true;
$plugins_string .= "<?php echo '/*%%SmartyNocache:{$this->properties['nocache_hash']}%%*/<?php \$_smarty = \$_smarty_tpl->smarty; ";
foreach ($this->required_plugins['nocache'] as $tmp) {
foreach ($tmp as $data) {
$file = addslashes($data['file']);
if (is_Array($data['function'])) {
$plugins_string .= addslashes("if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) include '{$file}';\n");
} else {
$plugins_string .= addslashes("if (!is_callable('{$data['function']}')) include '{$file}';\n");
}
}
}
$plugins_string .= "?>/*/%%SmartyNocache:{$this->properties['nocache_hash']}%%*/';?>\n";
}
$tpl = $this->setupSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope);
$tpl->properties['nocache_hash'] = $hash;
if (!isset($this->smarty->template_objects[$tpl->templateId])) {
$this->smarty->template_objects[$tpl->templateId] = $tpl;
}
// build property code
$this->properties['has_nocache_code'] = $this->has_nocache_code;
$output = '';
if (!$this->source->recompiled) {
$output = "<?php /*%%SmartyHeaderCode:{$this->properties['nocache_hash']}%%*/";
if ($this->smarty->direct_access_security) {
$output .= "if(!defined('SMARTY_DIR')) exit('no direct access allowed');\n";
}
if ($this->smarty->debugging) {
Smarty_Internal_Debug::start_template($tpl);
Smarty_Internal_Debug::start_render($tpl);
}
if ($cache) {
// remove compiled code of{function} definition
unset($this->properties['function']);
if (!empty($this->smarty->template_functions)) {
// copy code of {function} tags called in nocache mode
foreach ($this->smarty->template_functions as $name => $function_data) {
if (isset($function_data['called_nocache'])) {
foreach ($function_data['called_functions'] as $func_name) {
$this->smarty->template_functions[$func_name]['called_nocache'] = true;
}
}
}
foreach ($this->smarty->template_functions as $name => $function_data) {
if (isset($function_data['called_nocache'])) {
unset($function_data['called_nocache'], $function_data['called_functions'], $this->smarty->template_functions[$name]['called_nocache']);
$this->properties['function'][$name] = $function_data;
}
}
}
$tpl->properties['unifunc'] = $content_func;
$output = $tpl->getRenderedTemplateCode();
if ($this->smarty->debugging) {
Smarty_Internal_Debug::end_template($tpl);
Smarty_Internal_Debug::end_render($tpl);
}
$this->properties['version'] = Smarty::SMARTY_VERSION;
if (!isset($this->properties['unifunc'])) {
$this->properties['unifunc'] = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
}
if (!$this->source->recompiled) {
$output .= "\$_valid = \$_smarty_tpl->decodeProperties(" . var_export($this->properties, true) . ',' . ($cache ? 'true' : 'false') . "); /*/%%SmartyHeaderCode%%*/?>\n";
$output .= '<?php if ($_valid && !is_callable(\'' . $this->properties['unifunc'] . '\')) {function ' . $this->properties['unifunc'] . '($_smarty_tpl) {?>';
}
$output .= $plugins_string;
$output .= $content;
if (!$this->source->recompiled) {
$output .= "<?php }} ?>\n";
if (!empty($tpl->properties['file_dependency'])) {
$this->properties['file_dependency'] = array_merge($this->properties['file_dependency'], $tpl->properties['file_dependency']);
}
$this->properties['tpl_function'] = $tpl->properties['tpl_function'];
return str_replace($tpl->properties['nocache_hash'], $this->properties['nocache_hash'], $output);
}
return $output;
/**
* Call template function
*
* @param string $name template function name
* @param object|\Smarty_Internal_Template $_smarty_tpl template object
* @param array $params parameter array
* @param bool $nocache true if called nocache
*
* @throws \SmartyException
*/
public function callTemplateFunction($name, Smarty_Internal_Template $_smarty_tpl, $params, $nocache)
{
if (isset($_smarty_tpl->properties['tpl_function'][$name])) {
if (!$_smarty_tpl->caching || ($_smarty_tpl->caching && $nocache)) {
$function = $_smarty_tpl->properties['tpl_function'][$name]['call_name'];
} else {
if (isset($_smarty_tpl->properties['tpl_function'][$name]['call_name_caching'])) {
$function = $_smarty_tpl->properties['tpl_function'][$name]['call_name_caching'];
} else {
$function = $_smarty_tpl->properties['tpl_function'][$name]['call_name'];
}
}
if (function_exists($function)) {
$function ($_smarty_tpl, $params);
return;
}
// try to load template function dynamically
if (Smarty_Internal_Function_Call_Handler::call($name, $_smarty_tpl, $function, $params, $nocache)) {
$function ($_smarty_tpl, $params);
return;
}
}
throw new SmartyException("Unable to find template function '{$name}'");
}
/**
@ -447,33 +593,21 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
*/
public function decodeProperties($properties, $cache = false)
{
$this->has_nocache_code = $properties['has_nocache_code'];
$this->properties['nocache_hash'] = $properties['nocache_hash'];
if (isset($properties['cache_lifetime'])) {
$this->properties['cache_lifetime'] = $properties['cache_lifetime'];
}
if (isset($properties['file_dependency'])) {
$this->properties['file_dependency'] = array_merge($this->properties['file_dependency'], $properties['file_dependency']);
}
if (!empty($properties['function'])) {
$this->properties['function'] = array_merge($this->properties['function'], $properties['function']);
$this->smarty->template_functions = array_merge($this->smarty->template_functions, $properties['function']);
}
$this->properties['version'] = (isset($properties['version'])) ? $properties['version'] : '';
$this->properties['unifunc'] = $properties['unifunc'];
// check file dependencies at compiled code
$properties['version'] = (isset($properties['version'])) ? $properties['version'] : '';
$is_valid = true;
if ($this->properties['version'] != Smarty::SMARTY_VERSION) {
if (Smarty::SMARTY_VERSION != $properties['version']) {
// new version must rebuild
$is_valid = false;
} elseif (((!$cache && $this->smarty->compile_check && empty($this->compiled->_properties) && !$this->compiled->isCompiled) || $cache && ($this->smarty->compile_check === true || $this->smarty->compile_check === Smarty::COMPILECHECK_ON)) && !empty($this->properties['file_dependency'])) {
foreach ($this->properties['file_dependency'] as $_file_to_check) {
} elseif ((!$cache && $this->smarty->compile_check || $cache && ($this->smarty->compile_check === true || $this->smarty->compile_check === Smarty::COMPILECHECK_ON)) && !empty($properties['file_dependency'])) {
// check file dependencies at compiled code
foreach ($properties['file_dependency'] as $_file_to_check) {
if ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'php') {
if ($this->source->filepath == $_file_to_check[0] && isset($this->source->timestamp)) {
// do not recheck current template
$mtime = $this->source->timestamp;
} else {
// file and php types can be checked without loading the respective resource handlers
$mtime = @filemtime($_file_to_check[0]);
$mtime = is_file($_file_to_check[0]) ? @filemtime($_file_to_check[0]) : false;
}
} elseif ($_file_to_check[2] == 'string') {
continue;
@ -490,8 +624,8 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
if ($cache) {
// CACHING_LIFETIME_SAVED cache expiry has to be validated here since otherwise we'd define the unifunc
if ($this->caching === Smarty::CACHING_LIFETIME_SAVED &&
$this->properties['cache_lifetime'] >= 0 &&
(time() > ($this->cached->timestamp + $this->properties['cache_lifetime']))
$properties['cache_lifetime'] >= 0 &&
(time() > ($this->cached->timestamp + $properties['cache_lifetime']))
) {
$is_valid = false;
}
@ -499,25 +633,35 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
} else {
$this->mustCompile = !$is_valid;
}
// store data in reusable Smarty_Template_Compiled
if (!$cache) {
$this->compiled->_properties = $properties;
if ($is_valid) {
$this->has_nocache_code = $properties['has_nocache_code'];
// $this->properties['nocache_hash'] = $properties['nocache_hash'];
if (isset($properties['cache_lifetime'])) {
$this->properties['cache_lifetime'] = $properties['cache_lifetime'];
}
if (isset($properties['file_dependency'])) {
$this->properties['file_dependency'] = array_merge($this->properties['file_dependency'], $properties['file_dependency']);
}
if (isset($properties['tpl_function'])) {
$this->properties['tpl_function'] = array_merge($this->properties['tpl_function'], $properties['tpl_function']);
}
$this->properties['version'] = $properties['version'];
$this->properties['unifunc'] = $properties['unifunc'];
}
return $is_valid;
}
/**
* Template code runtime function to create a local Smarty variable for array assignments
*
* @param string $tpl_var tempate variable name
* @param string $tpl_var template variable name
* @param bool $nocache cache mode of variable
* @param int $scope scope of variable
*/
public function createLocalArrayVariable($tpl_var, $nocache = false, $scope = Smarty::SCOPE_LOCAL)
{
if (!isset($this->tpl_vars[$tpl_var])) {
$this->tpl_vars[$tpl_var] = new Smarty_variable(array(), $nocache, $scope);
$this->tpl_vars[$tpl_var] = new Smarty_Variable(array(), $nocache, $scope);
} else {
$this->tpl_vars[$tpl_var] = clone $this->tpl_vars[$tpl_var];
if ($scope != Smarty::SCOPE_LOCAL) {
@ -558,7 +702,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
/**
* Get parent or root of template parent chain
*
* @param int $scope pqrent or root scope
* @param int $scope parent or root scope
*
* @return mixed object
*/
@ -579,11 +723,12 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
}
/**
* [util function] counts an array, arrayaccess/traversable or PDOStatement object
* [util function] counts an array, arrayAccess/traversable or PDOStatement object
*
* @param mixed $value
*
* @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0 for empty elements
* @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0
* for empty elements
*/
public function _count($value)
{
@ -612,7 +757,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
/**
* runtime error not matching capture tags
*/
public function capture_error()
{
@ -630,7 +774,78 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
{
Smarty_CacheResource::invalidLoadedCache($this->smarty);
return $this->cached->handler->clear($this->smarty, $this->template_name, $this->cache_id, $this->compile_id, $exp_time);
return $this->cached->handler->clear($this->smarty, $this->template_resource, $this->cache_id, $this->compile_id, $exp_time);
}
/**
* Load source resource
*
* @throws SmartyException
*/
public function loadSource()
{
$this->source = Smarty_Template_Source::load($this);
if ($this->smarty->template_resource_caching && !$this->source->recompiled && isset($this->templateId)) {
$this->smarty->template_objects[$this->templateId] = $this;
}
}
/**
* Load compiled object
*
*/
public function loadCompiled()
{
if (!isset($this->compiled)) {
if (!class_exists('Smarty_Template_Compiled', false)) {
require SMARTY_SYSPLUGINS_DIR . 'smarty_template_compiled.php';
}
$this->compiled = Smarty_Template_Compiled::load($this);
}
}
/**
* Load cached object
*
*/
public function loadCached()
{
if (!isset($this->cached)) {
if (!class_exists('Smarty_Template_Cached', false)) {
require SMARTY_SYSPLUGINS_DIR . 'smarty_template_cached.php';
}
$this->cached = Smarty_Template_Cached::load($this);
}
}
/**
* Load compiler object
*
* @throws \SmartyException
*/
public function loadCompiler()
{
$this->smarty->loadPlugin($this->source->compiler_class);
$this->compiler = new $this->source->compiler_class($this->source->template_lexer_class, $this->source->template_parser_class, $this->smarty);
}
/**
* Handle unknown class methods
*
* @param string $name unknown method-name
* @param array $args argument array
*
* @return mixed
* @throws SmartyException
*/
public function __call($name, $args)
{
// method of Smarty object?
if (method_exists($this->smarty, $name)) {
return call_user_func_array(array($this->smarty, $name), $args);
}
// parent
return parent::__call($name, $args);
}
/**
@ -649,18 +864,14 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
case 'cached':
case 'compiler':
$this->$property_name = $value;
return;
// FIXME: routing of template -> smarty attributes
default:
// Smarty property ?
if (property_exists($this->smarty, $property_name)) {
$this->smarty->$property_name = $value;
return;
}
}
throw new SmartyException("invalid template property '$property_name'.");
}
@ -669,65 +880,38 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
*
* @param string $property_name property name
*
* @return mixed|Smarty_Template_Cached
* @throws SmartyException
*/
public function __get($property_name)
{
switch ($property_name) {
case 'source':
if (strlen($this->template_resource) == 0) {
throw new SmartyException('Missing template name');
}
$this->source = Smarty_Resource::source($this);
// cache template object under a unique ID
// do not cache eval resources
if ($this->source->type != 'eval') {
if ($this->smarty->allow_ambiguous_resources) {
$_templateId = $this->source->unique_resource . $this->cache_id . $this->compile_id;
} else {
$_templateId = $this->smarty->joined_template_dir . '#' . $this->template_resource . $this->cache_id . $this->compile_id;
}
if (isset($_templateId[150])) {
$_templateId = sha1($_templateId);
}
$this->smarty->template_objects[$_templateId] = $this;
}
$this->loadSource();
return $this->source;
case 'compiled':
$this->compiled = $this->source->getCompiled($this);
$this->loadCompiled();
return $this->compiled;
case 'cached':
if (!class_exists('Smarty_Template_Cached')) {
include SMARTY_SYSPLUGINS_DIR . 'smarty_cacheresource.php';
}
$this->cached = new Smarty_Template_Cached($this);
$this->loadCached();
return $this->cached;
case 'compiler':
$this->smarty->loadPlugin($this->source->compiler_class);
$this->compiler = new $this->source->compiler_class($this->source->template_lexer_class, $this->source->template_parser_class, $this->smarty);
$this->loadCompiler();
return $this->compiler;
// FIXME: routing of template -> smarty attributes
default:
// Smarty property ?
if (property_exists($this->smarty, $property_name)) {
return $this->smarty->$property_name;
}
}
throw new SmartyException("template property '$property_name' does not exist.");
}
/**
* Template data object destructor
*/
public function __destruct()
{

View File

@ -17,382 +17,31 @@
abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
{
/**
* fetches a rendered Smarty template
* Set this if you want different sets of cache files for the same
* templates.
*
* @param string $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
* @param bool $display true: display, false: fetch
* @param bool $merge_tpl_vars if true parent template variables merged in to local scope
* @param bool $no_output_filter if true do not run output filter
*
* @throws Exception
* @throws SmartyException
* @return string rendered template output
* @var string
*/
public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false)
{
if ($template === null && $this instanceof $this->template_class) {
$template = $this;
}
if ($cache_id !== null && is_object($cache_id)) {
$parent = $cache_id;
$cache_id = null;
}
if ($parent === null && ($this instanceof Smarty || is_string($template))) {
$parent = $this;
}
// create template object if necessary
$_template = ($template instanceof $this->template_class)
? $template
: $this->smarty->createTemplate($template, $cache_id, $compile_id, $parent, false);
// if called by Smarty object make sure we use current caching status
if ($this instanceof Smarty) {
$_template->caching = $this->caching;
}
// merge all variable scopes into template
if ($merge_tpl_vars) {
// save local variables
$save_tpl_vars = $_template->tpl_vars;
$save_config_vars = $_template->config_vars;
$ptr_array = array($_template);
$ptr = $_template;
while (isset($ptr->parent)) {
$ptr_array[] = $ptr = $ptr->parent;
}
$ptr_array = array_reverse($ptr_array);
$parent_ptr = reset($ptr_array);
$tpl_vars = $parent_ptr->tpl_vars;
$config_vars = $parent_ptr->config_vars;
while ($parent_ptr = next($ptr_array)) {
if (!empty($parent_ptr->tpl_vars)) {
$tpl_vars = array_merge($tpl_vars, $parent_ptr->tpl_vars);
}
if (!empty($parent_ptr->config_vars)) {
$config_vars = array_merge($config_vars, $parent_ptr->config_vars);
}
}
if (!empty(Smarty::$global_tpl_vars)) {
$tpl_vars = array_merge(Smarty::$global_tpl_vars, $tpl_vars);
}
$_template->tpl_vars = $tpl_vars;
$_template->config_vars = $config_vars;
}
// dummy local smarty variable
if (!isset($_template->tpl_vars['smarty'])) {
$_template->tpl_vars['smarty'] = new Smarty_Variable;
}
if (isset($this->smarty->error_reporting)) {
$_smarty_old_error_level = error_reporting($this->smarty->error_reporting);
}
// check URL debugging control
if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') {
if (isset($_SERVER['QUERY_STRING'])) {
$_query_string = $_SERVER['QUERY_STRING'];
} else {
$_query_string = '';
}
if (false !== strpos($_query_string, $this->smarty->smarty_debug_id)) {
if (false !== strpos($_query_string, $this->smarty->smarty_debug_id . '=on')) {
// enable debugging for this browser session
setcookie('SMARTY_DEBUG', true);
$this->smarty->debugging = true;
} elseif (false !== strpos($_query_string, $this->smarty->smarty_debug_id . '=off')) {
// disable debugging for this browser session
setcookie('SMARTY_DEBUG', false);
$this->smarty->debugging = false;
} else {
// enable debugging for this page
$this->smarty->debugging = true;
}
} else {
if (isset($_COOKIE['SMARTY_DEBUG'])) {
$this->smarty->debugging = true;
}
}
}
// must reset merge template date
$_template->smarty->merged_templates_func = array();
// get rendered template
// disable caching for evaluated code
if ($_template->source->recompiled) {
$_template->caching = false;
}
// checks if template exists
if (!$_template->source->exists) {
if ($_template->parent instanceof Smarty_Internal_Template) {
$parent_resource = " in '{$_template->parent->template_resource}'";
} else {
$parent_resource = '';
}
throw new SmartyException("Unable to load template {$_template->source->type} '{$_template->source->name}'{$parent_resource}");
}
// read from cache or render
if (!($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || $_template->caching == Smarty::CACHING_LIFETIME_SAVED) || !$_template->cached->valid) {
// render template (not loaded and not in cache)
if (!$_template->source->uncompiled) {
/** @var Smarty_Internal_Template $_smarty_tpl
* used in evaluated code
*/
$_smarty_tpl = $_template;
if ($_template->source->recompiled) {
$code = $_template->compiler->compileTemplate($_template);
if ($this->smarty->debugging) {
Smarty_Internal_Debug::start_render($_template);
}
try {
ob_start();
eval("?>" . $code);
unset($code);
}
catch (Exception $e) {
ob_get_clean();
throw $e;
}
} else {
if (!$_template->compiled->exists || ($_template->smarty->force_compile && !$_template->compiled->isCompiled)) {
$_template->compileTemplateSource();
$code = file_get_contents($_template->compiled->filepath);
eval("?>" . $code);
unset($code);
$_template->compiled->loaded = true;
$_template->compiled->isCompiled = true;
}
if ($this->smarty->debugging) {
Smarty_Internal_Debug::start_render($_template);
}
if (!$_template->compiled->loaded) {
include($_template->compiled->filepath);
if ($_template->mustCompile) {
// recompile and load again
$_template->compileTemplateSource();
$code = file_get_contents($_template->compiled->filepath);
eval("?>" . $code);
unset($code);
$_template->compiled->isCompiled = true;
}
$_template->compiled->loaded = true;
} else {
$_template->decodeProperties($_template->compiled->_properties, false);
}
try {
ob_start();
if (empty($_template->properties['unifunc']) || !is_callable($_template->properties['unifunc'])) {
throw new SmartyException("Invalid compiled template for '{$_template->template_resource}'");
}
array_unshift($_template->_capture_stack, array());
//
// render compiled template
//
$_template->properties['unifunc']($_template);
// any unclosed {capture} tags ?
if (isset($_template->_capture_stack[0][0])) {
$_template->capture_error();
}
array_shift($_template->_capture_stack);
}
catch (Exception $e) {
ob_get_clean();
throw $e;
}
}
} else {
if ($_template->source->uncompiled) {
if ($this->smarty->debugging) {
Smarty_Internal_Debug::start_render($_template);
}
try {
ob_start();
$_template->source->renderUncompiled($_template);
}
catch (Exception $e) {
ob_get_clean();
throw $e;
}
} else {
throw new SmartyException("Resource '$_template->source->type' must have 'renderUncompiled' method");
}
}
$_output = ob_get_clean();
if (!$_template->source->recompiled && empty($_template->properties['file_dependency'][$_template->source->uid])) {
$_template->properties['file_dependency'][$_template->source->uid] = array($_template->source->filepath, $_template->source->timestamp, $_template->source->type);
}
if ($_template->parent instanceof Smarty_Internal_Template) {
$_template->parent->properties['file_dependency'] = array_merge($_template->parent->properties['file_dependency'], $_template->properties['file_dependency']);
foreach ($_template->required_plugins as $code => $tmp1) {
foreach ($tmp1 as $name => $tmp) {
foreach ($tmp as $type => $data) {
$_template->parent->required_plugins[$code][$name][$type] = $data;
}
}
}
}
if ($this->smarty->debugging) {
Smarty_Internal_Debug::end_render($_template);
}
// write to cache when nessecary
if (!$_template->source->recompiled && ($_template->caching == Smarty::CACHING_LIFETIME_SAVED || $_template->caching == Smarty::CACHING_LIFETIME_CURRENT)) {
if ($this->smarty->debugging) {
Smarty_Internal_Debug::start_cache($_template);
}
$_template->properties['has_nocache_code'] = false;
// get text between non-cached items
$cache_split = preg_split("!/\*%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!s", $_output);
// get non-cached items
preg_match_all("!/\*%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!s", $_output, $cache_parts);
$output = '';
// loop over items, stitch back together
foreach ($cache_split as $curr_idx => $curr_split) {
// escape PHP tags in template content
$output .= preg_replace('/(<%|%>|<\?php|<\?|\?>|<script\s+language\s*=\s*[\"\']?\s*php\s*[\"\']?\s*>)/', "<?php echo '\$1'; ?>\n", $curr_split);
if (isset($cache_parts[0][$curr_idx])) {
$_template->properties['has_nocache_code'] = true;
// remove nocache tags from cache output
$output .= preg_replace("!/\*/?%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!", '', $cache_parts[0][$curr_idx]);
}
}
if (!$no_output_filter && !$_template->has_nocache_code && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) {
$output = Smarty_Internal_Filter_Handler::runFilter('output', $output, $_template);
}
// rendering (must be done before writing cache file because of {function} nocache handling)
/** @var Smarty_Internal_Template $_smarty_tpl
* used in evaluated code
*/
$_smarty_tpl = $_template;
try {
ob_start();
eval("?>" . $output);
$_output = ob_get_clean();
}
catch (Exception $e) {
ob_get_clean();
throw $e;
}
// write cache file content
$_template->writeCachedContent($output);
if ($this->smarty->debugging) {
Smarty_Internal_Debug::end_cache($_template);
}
} else {
// var_dump('renderTemplate', $_template->has_nocache_code, $_template->template_resource, $_template->properties['nocache_hash'], $_template->parent->properties['nocache_hash'], $_output);
if (!empty($_template->properties['nocache_hash']) && !empty($_template->parent->properties['nocache_hash'])) {
// replace nocache_hash
$_output = str_replace("{$_template->properties['nocache_hash']}", $_template->parent->properties['nocache_hash'], $_output);
$_template->parent->has_nocache_code = $_template->parent->has_nocache_code || $_template->has_nocache_code;
}
}
} else {
if ($this->smarty->debugging) {
Smarty_Internal_Debug::start_cache($_template);
}
try {
ob_start();
array_unshift($_template->_capture_stack, array());
//
// render cached template
//
$_template->properties['unifunc']($_template);
// any unclosed {capture} tags ?
if (isset($_template->_capture_stack[0][0])) {
$_template->capture_error();
}
array_shift($_template->_capture_stack);
$_output = ob_get_clean();
}
catch (Exception $e) {
ob_get_clean();
throw $e;
}
if ($this->smarty->debugging) {
Smarty_Internal_Debug::end_cache($_template);
}
}
if ((!$this->caching || $_template->has_nocache_code || $_template->source->recompiled) && !$no_output_filter && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) {
$_output = Smarty_Internal_Filter_Handler::runFilter('output', $_output, $_template);
}
if (isset($this->error_reporting)) {
error_reporting($_smarty_old_error_level);
}
// display or fetch
if ($display) {
if ($this->caching && $this->cache_modified_check) {
$_isCached = $_template->isCached() && !$_template->has_nocache_code;
$_last_modified_date = @substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);
if ($_isCached && $_template->cached->timestamp <= strtotime($_last_modified_date)) {
switch (PHP_SAPI) {
case 'cgi': // php-cgi < 5.3
case 'cgi-fcgi': // php-cgi >= 5.3
case 'fpm-fcgi': // php-fpm >= 5.3.3
header('Status: 304 Not Modified');
break;
case 'cli':
if ( /* ^phpunit */
!empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS']) /* phpunit$ */
) {
$_SERVER['SMARTY_PHPUNIT_HEADERS'][] = '304 Not Modified';
}
break;
default:
header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
break;
}
} else {
switch (PHP_SAPI) {
case 'cli':
if ( /* ^phpunit */
!empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS']) /* phpunit$ */
) {
$_SERVER['SMARTY_PHPUNIT_HEADERS'][] = 'Last-Modified: ' . gmdate('D, d M Y H:i:s', $_template->cached->timestamp) . ' GMT';
}
break;
default:
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $_template->cached->timestamp) . ' GMT');
break;
}
echo $_output;
}
} else {
echo $_output;
}
// debug output
if ($this->smarty->debugging) {
Smarty_Internal_Debug::display_debug($_template);
}
if ($merge_tpl_vars) {
// restore local variables
$_template->tpl_vars = $save_tpl_vars;
$_template->config_vars = $save_config_vars;
}
return;
} else {
if ($merge_tpl_vars) {
// restore local variables
$_template->tpl_vars = $save_tpl_vars;
$_template->config_vars = $save_config_vars;
}
// return fetched content
return $_output;
}
}
public $cache_id = null;
/**
* displays a Smarty template
* Set this if you want different sets of compiled files for the same
* templates.
*
* @param string $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
* @var string
*/
public function display($template = null, $cache_id = null, $compile_id = null, $parent = null)
{
// display template
$this->fetch($template, $cache_id, $compile_id, $parent, true);
}
public $compile_id = null;
/**
* caching enabled
*
* @var boolean
*/
public $caching = false;
/**
* cache lifetime in seconds
*
* @var integer
*/
public $cache_lifetime = 3600;
/**
* test if cache is valid
@ -407,28 +56,63 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null)
{
if ($template === null && $this instanceof $this->template_class) {
return $this->cached->valid;
}
if (!($template instanceof $this->template_class)) {
if ($parent === null) {
$parent = $this;
$template = $this;
} else {
if (!($template instanceof $this->template_class)) {
if ($parent === null) {
$parent = $this;
}
$smarty = isset($this->smarty) ? $this->smarty : $this;
$template = $smarty->createTemplate($template, $cache_id, $compile_id, $parent, false);
}
$template = $this->smarty->createTemplate($template, $cache_id, $compile_id, $parent, false);
}
// return cache status of template
return $template->cached->valid;
if (!isset($template->cached)) {
$template->loadCached();
}
return $template->cached->isCached($template);
}
/**
* creates a data object
*
* @param object $parent next higher level of Smarty variables
* @param string $name optional data block name
*
* @returns Smarty_Data data object
*/
public function createData($parent = null)
public function createData($parent = null, $name = null)
{
return new Smarty_Data($parent, $this);
$dataObj = new Smarty_Data($parent, $this, $name);
if ($this->debugging) {
Smarty_Internal_Debug::register_data($dataObj);
}
return $dataObj;
}
/**
* Get unique template id
*
* @param string $template_name
* @param null|mixed $cache_id
* @param null|mixed $compile_id
*
* @return string
*/
public function getTemplateId($template_name, $cache_id = null, $compile_id = null)
{
$cache_id = isset($cache_id) ? $cache_id : $this->cache_id;
$compile_id = isset($compile_id) ? $compile_id : $this->compile_id;
$smarty = isset($this->smarty) ? $this->smarty : $this;
if ($smarty->allow_ambiguous_resources) {
$_templateId = Smarty_Resource::getUniqueTemplateName($this, $template_name) . "#{$cache_id}#{$compile_id}";
} else {
$_templateId = $smarty->joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}";
}
if (isset($_templateId[150])) {
$_templateId = sha1($_templateId);
}
return $_templateId;
}
/**
@ -440,17 +124,19 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
* @param boolean $cacheable if true (default) this fuction is cachable
* @param array $cache_attr caching attributes if any
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
* @throws SmartyException when the plugin tag is invalid
*/
public function registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = null)
{
if (isset($this->smarty->registered_plugins[$type][$tag])) {
$smarty = isset($this->smarty) ? $this->smarty : $this;
if (isset($smarty->registered_plugins[$type][$tag])) {
throw new SmartyException("Plugin tag \"{$tag}\" already registered");
} elseif (!is_callable($callback)) {
throw new SmartyException("Plugin \"{$tag}\" not callable");
} else {
$this->smarty->registered_plugins[$type][$tag] = array($callback, (bool) $cacheable, (array) $cache_attr);
$smarty->registered_plugins[$type][$tag] = array($callback, (bool) $cacheable, (array) $cache_attr);
}
return $this;
@ -462,12 +148,14 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
* @param string $type of plugin
* @param string $tag name of plugin
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
*/
public function unregisterPlugin($type, $tag)
{
if (isset($this->smarty->registered_plugins[$type][$tag])) {
unset($this->smarty->registered_plugins[$type][$tag]);
$smarty = isset($this->smarty) ? $this->smarty : $this;
if (isset($smarty->registered_plugins[$type][$tag])) {
unset($smarty->registered_plugins[$type][$tag]);
}
return $this;
@ -477,13 +165,16 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
* Registers a resource to fetch a template
*
* @param string $type name of resource type
* @param Smarty_Resource|array $callback or instance of Smarty_Resource, or array of callbacks to handle resource (deprecated)
* @param Smarty_Resource|array $callback or instance of Smarty_Resource, or array of callbacks to handle resource
* (deprecated)
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
*/
public function registerResource($type, $callback)
{
$this->smarty->registered_resources[$type] = $callback instanceof Smarty_Resource ? $callback : array($callback, false);
$smarty = isset($this->smarty) ? $this->smarty : $this;
$smarty->registered_resources[$type] = $callback instanceof Smarty_Resource ? $callback : array($callback, false);
return $this;
}
@ -493,12 +184,14 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
*
* @param string $type name of resource type
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
*/
public function unregisterResource($type)
{
if (isset($this->smarty->registered_resources[$type])) {
unset($this->smarty->registered_resources[$type]);
$smarty = isset($this->smarty) ? $this->smarty : $this;
if (isset($smarty->registered_resources[$type])) {
unset($smarty->registered_resources[$type]);
}
return $this;
@ -510,11 +203,13 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
* @param string $type name of cache resource type
* @param Smarty_CacheResource $callback instance of Smarty_CacheResource to handle output caching
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
*/
public function registerCacheResource($type, Smarty_CacheResource $callback)
{
$this->smarty->registered_cache_resources[$type] = $callback;
$smarty = isset($this->smarty) ? $this->smarty : $this;
$smarty->registered_cache_resources[$type] = $callback;
return $this;
}
@ -524,12 +219,14 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
*
* @param string $type name of cache resource type
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
*/
public function unregisterCacheResource($type)
{
if (isset($this->smarty->registered_cache_resources[$type])) {
unset($this->smarty->registered_cache_resources[$type]);
$smarty = isset($this->smarty) ? $this->smarty : $this;
if (isset($smarty->registered_cache_resources[$type])) {
unset($smarty->registered_cache_resources[$type]);
}
return $this;
@ -545,7 +242,8 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
* @param array $block_methods list of block-methods
*
* @throws SmartyException
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
*/
public function registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())
{
@ -566,7 +264,8 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
}
}
// register the object
$this->smarty->registered_objects[$object_name] =
$smarty = isset($this->smarty) ? $this->smarty : $this;
$smarty->registered_objects[$object_name] =
array($object_impl, (array) $allowed, (boolean) $smarty_args, (array) $block_methods);
return $this;
@ -582,14 +281,15 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
*/
public function getRegisteredObject($name)
{
if (!isset($this->smarty->registered_objects[$name])) {
$smarty = isset($this->smarty) ? $this->smarty : $this;
if (!isset($smarty->registered_objects[$name])) {
throw new SmartyException("'$name' is not a registered object");
}
if (!is_object($this->smarty->registered_objects[$name][0])) {
if (!is_object($smarty->registered_objects[$name][0])) {
throw new SmartyException("registered '$name' is not an object");
}
return $this->smarty->registered_objects[$name][0];
return $smarty->registered_objects[$name][0];
}
/**
@ -597,12 +297,14 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
*
* @param string $name object name
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
*/
public function unregisterObject($name)
{
if (isset($this->smarty->registered_objects[$name])) {
unset($this->smarty->registered_objects[$name]);
$smarty = isset($this->smarty) ? $this->smarty : $this;
if (isset($smarty->registered_objects[$name])) {
unset($smarty->registered_objects[$name]);
}
return $this;
@ -615,7 +317,8 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
* @param string $class_impl the referenced PHP class to register
*
* @throws SmartyException
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
*/
public function registerClass($class_name, $class_impl)
{
@ -624,7 +327,8 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
throw new SmartyException("Undefined class '$class_impl' in register template class");
}
// register the class
$this->smarty->registered_classes[$class_name] = $class_impl;
$smarty = isset($this->smarty) ? $this->smarty : $this;
$smarty->registered_classes[$class_name] = $class_impl;
return $this;
}
@ -634,13 +338,15 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
*
* @param callable $callback class/method name
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
* @throws SmartyException if $callback is not callable
*/
public function registerDefaultPluginHandler($callback)
{
$smarty = isset($this->smarty) ? $this->smarty : $this;
if (is_callable($callback)) {
$this->smarty->default_plugin_handler_func = $callback;
$smarty->default_plugin_handler_func = $callback;
} else {
throw new SmartyException("Default plugin handler '$callback' not callable");
}
@ -653,17 +359,13 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
*
* @param callable $callback class/method name
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
* @throws SmartyException if $callback is not callable
*/
public function registerDefaultTemplateHandler($callback)
{
if (is_callable($callback)) {
$this->smarty->default_template_handler_func = $callback;
} else {
throw new SmartyException("Default template handler '$callback' not callable");
}
Smarty_Internal_Extension_DefaultTemplateHandler::registerDefaultTemplateHandler($this, $callback);
return $this;
}
@ -672,17 +374,13 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
*
* @param callable $callback class/method name
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
* @throws SmartyException if $callback is not callable
*/
public function registerDefaultConfigHandler($callback)
{
if (is_callable($callback)) {
$this->smarty->default_config_handler_func = $callback;
} else {
throw new SmartyException("Default config handler '$callback' not callable");
}
Smarty_Internal_Extension_DefaultTemplateHandler::registerDefaultConfigHandler($this, $callback);
return $this;
}
@ -692,11 +390,13 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
* @param string $type filter type
* @param callback $callback
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
*/
public function registerFilter($type, $callback)
{
$this->smarty->registered_filters[$type][$this->_get_filter_name($callback)] = $callback;
$smarty = isset($this->smarty) ? $this->smarty : $this;
$smarty->registered_filters[$type][$this->_get_filter_name($callback)] = $callback;
return $this;
}
@ -707,13 +407,15 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
* @param string $type filter type
* @param callback $callback
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
*/
public function unregisterFilter($type, $callback)
{
$name = $this->_get_filter_name($callback);
if (isset($this->smarty->registered_filters[$type][$name])) {
unset($this->smarty->registered_filters[$type][$name]);
$smarty = isset($this->smarty) ? $this->smarty : $this;
if (isset($smarty->registered_filters[$type][$name])) {
unset($smarty->registered_filters[$type][$name]);
}
return $this;
@ -748,14 +450,15 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
*/
public function loadFilter($type, $name)
{
$smarty = isset($this->smarty) ? $this->smarty : $this;
$_plugin = "smarty_{$type}filter_{$name}";
$_filter_name = $_plugin;
if ($this->smarty->loadPlugin($_plugin)) {
if ($smarty->loadPlugin($_plugin)) {
if (class_exists($_plugin, false)) {
$_plugin = array($_plugin, 'execute');
}
if (is_callable($_plugin)) {
$this->smarty->registered_filters[$type][$_filter_name] = $_plugin;
$smarty->registered_filters[$type][$_filter_name] = $_plugin;
return true;
}
@ -769,13 +472,15 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
* @param string $type filter type
* @param string $name filter name
*
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining
* @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or
* Smarty_Internal_Template) instance for chaining
*/
public function unloadFilter($type, $name)
{
$smarty = isset($this->smarty) ? $this->smarty : $this;
$_filter_name = "smarty_{$type}filter_{$name}";
if (isset($this->smarty->registered_filters[$type][$_filter_name])) {
unset ($this->smarty->registered_filters[$type][$_filter_name]);
if (isset($smarty->registered_filters[$type][$_filter_name])) {
unset ($smarty->registered_filters[$type][$_filter_name]);
}
return $this;
@ -807,10 +512,6 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
static $_resolved_property_name = array();
static $_resolved_property_source = array();
// method of Smarty object?
if (method_exists($this->smarty, $name)) {
return call_user_func_array(array($this->smarty, $name), $args);
}
// see if this is a set/get for a property
$first3 = strtolower(substr($name, 0, 3));
if (isset($_prefixes[$first3]) && isset($name[3]) && $name[3] !== '_') {
@ -825,36 +526,32 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
$_resolved_property_name[$name] = $property_name;
}
if (isset($_resolved_property_source[$property_name])) {
$_is_this = $_resolved_property_source[$property_name];
$status = $_resolved_property_source[$property_name];
} else {
$_is_this = null;
$status = null;
if (property_exists($this, $property_name)) {
$_is_this = true;
$status = true;
} elseif (property_exists($this->smarty, $property_name)) {
$_is_this = false;
$status = false;
}
$_resolved_property_source[$property_name] = $_is_this;
$_resolved_property_source[$property_name] = $status;
}
if ($_is_this) {
$smarty = null;
if ($status === true) {
$smarty = $this;
} elseif ($status === false) {
$smarty = $this->smarty;
}
if ($smarty) {
if ($first3 == 'get') {
return $this->$property_name;
return $smarty->$property_name;
} else {
return $this->$property_name = $args[0];
return $smarty->$property_name = $args[0];
}
} elseif ($_is_this === false) {
if ($first3 == 'get') {
return $this->smarty->$property_name;
} else {
return $this->smarty->$property_name = $args[0];
}
} else {
throw new SmartyException("property '$property_name' does not exist.");
}
}
throw new SmartyException("property '$property_name' does not exist.");
}
if ($name == 'Smarty') {
throw new SmartyException("PHP5 requires you to call __construct() instead of Smarty()");
}
// must be unknown
throw new SmartyException("Call of unknown method '$name'.");
}
}

View File

@ -17,12 +17,20 @@
*/
abstract class Smarty_Internal_TemplateCompilerBase
{
/**
* Smarty object
*
* @var Smarty
*/
public $smarty = null;
/**
* hash for nocache sections
*
* @var mixed
*/
private $nocache_hash = null;
public $nocache_hash = null;
/**
* suppress generation of nocache code
@ -31,13 +39,6 @@ abstract class Smarty_Internal_TemplateCompilerBase
*/
public $suppressNocacheProcessing = false;
/**
* suppress generation of merged template code
*
* @var bool
*/
public $suppressMergedTemplates = false;
/**
* compile tag objects
*
@ -60,11 +61,25 @@ abstract class Smarty_Internal_TemplateCompilerBase
public $template = null;
/**
* merged templates
* merged included sub template data
*
* @var array
*/
public $merged_templates = array();
public $mergedSubTemplatesData = array();
/**
* merged sub template code
*
* @var array
*/
public $mergedSubTemplatesCode = array();
/**
* collected template properties during compilation
*
* @var array
*/
public $templateProperties = array();
/**
* sources which must be compiled
@ -114,6 +129,7 @@ abstract class Smarty_Internal_TemplateCompilerBase
* @var string
*/
public $trace_filepath = '';
/**
* stack for tracing file and line of nested {block} tags
*
@ -178,12 +194,26 @@ abstract class Smarty_Internal_TemplateCompilerBase
public $compiles_template_function = false;
/**
* called subfuntions from template function
* called sub functions from template function
*
* @var array
*/
public $called_functions = array();
/**
* compiled template function code
*
* @var string
*/
public $templateFunctionCode = '';
/**
* php_handling setting either from Smarty or security
*
* @var int
*/
public $php_handling = 0;
/**
* flags for used modifier plugins
*
@ -198,6 +228,76 @@ abstract class Smarty_Internal_TemplateCompilerBase
*/
public $known_modifier_type = array();
/**
* parent compiler object for merged subtemplates and template functions
*
* @var Smarty_Internal_TemplateCompilerBase
*/
public $parent_compiler = null;
/**
* Flag true when compiling nocache section
*
* @var bool
*/
public $nocache = false;
/**
* Flag true when tag is compiled as nocache
*
* @var bool
*/
public $tag_nocache = false;
/**
* Flag to restart parsing
*
* @var bool
*/
public $abort_and_recompile = false;
/**
* Compiled tag prefix code
*
* @var array
*/
public $prefix_code = array();
/**
* Prefix code stack
*
* @var array
*/
public $prefixCodeStack = array();
/**
* Tag has compiled code
*
* @var bool
*/
public $has_code = false;
/**
* A variable string was compiled
*
* @var bool
*/
public $has_variable_string = false;
/**
* Tag creates output
*
* @var bool
*/
public $has_output = false;
/**
* Strip preg pattern
*
* @var string
*/
public $stripRegEx = '![\t ]*[\r\n]+[\t ]*!';
/**
* method to compile a Smarty template
*
@ -212,31 +312,34 @@ abstract class Smarty_Internal_TemplateCompilerBase
*/
public function __construct()
{
$this->nocache_hash = str_replace(array('.', ','), '-', uniqid(rand(), true));
$this->nocache_hash = str_replace(array('.', ','), '_', uniqid(rand(), true));
}
/**
* Method to compile a Smarty template
*
* @param Smarty_Internal_Template $template template object to compile
* @param bool $nocache true is shall be compiled in nocache mode
* @param Smarty_Internal_Template $template template object to compile
* @param bool $nocache true is shall be compiled in nocache mode
* @param null|Smarty_Internal_TemplateCompilerBase $parent_compiler
*
* @return bool true if compiling succeeded, false if it failed
* @return bool true if compiling succeeded, false if it failed
*/
public function compileTemplate(Smarty_Internal_Template $template, $nocache = false)
public function compileTemplate(Smarty_Internal_Template $template, $nocache = null, $parent_compiler = null)
{
// save template object in compiler class
$this->template = $template;
if (isset($this->template->smarty->security_policy)) {
$this->php_handling = $this->template->smarty->security_policy->php_handling;
} else {
$this->php_handling = $this->template->smarty->php_handling;
}
$this->parent_compiler = $parent_compiler ? $parent_compiler : $this;
$nocache = isset($nocache) ? $nocache : false;
if (empty($template->properties['nocache_hash'])) {
$template->properties['nocache_hash'] = $this->nocache_hash;
} else {
$this->nocache_hash = $template->properties['nocache_hash'];
}
// flag for nochache sections
$this->nocache = $nocache;
$this->tag_nocache = false;
// save template object in compiler class
$this->template = $template;
// reset has nocache code flag
$this->template->has_nocache_code = false;
$save_source = $this->template->source;
// template header code
$template_header = '';
@ -259,9 +362,7 @@ abstract class Smarty_Internal_TemplateCompilerBase
Smarty_Internal_Debug::start_compile($this->template);
}
$no_sources = count($this->sources);
if ($loop || $no_sources) {
$this->template->properties['file_dependency'][$this->template->source->uid] = array($this->template->source->filepath, $this->template->source->timestamp, $this->template->source->type);
}
$this->parent_compiler->template->properties['file_dependency'][$this->template->source->uid] = array($this->template->source->filepath, $this->template->source->timestamp, $this->template->source->type);
$loop ++;
if ($no_sources) {
$this->inheritance_child = true;
@ -269,6 +370,13 @@ abstract class Smarty_Internal_TemplateCompilerBase
$this->inheritance_child = false;
}
do {
// flag for nochache sections
$this->nocache = $nocache;
$this->tag_nocache = false;
// reset has nocache code flag
$this->template->has_nocache_code = false;
$this->has_variable_string = false;
$this->prefix_code = array();
$_compiled_code = '';
// flag for aborting current and start recompile
$this->abort_and_recompile = false;
@ -280,7 +388,7 @@ abstract class Smarty_Internal_TemplateCompilerBase
$_content = Smarty_Internal_Filter_Handler::runFilter('pre', $_content, $template);
}
// call compiler
$_compiled_code = $this->doCompile($_content);
$_compiled_code = $this->doCompile($_content, true);
}
} while ($this->abort_and_recompile);
if ($this->smarty->debugging) {
@ -292,12 +400,12 @@ abstract class Smarty_Internal_TemplateCompilerBase
unset($save_source);
$this->smarty->_current_file = $this->template->source->filepath;
// free memory
unset($this->parser->root_buffer, $this->parser->current_buffer, $this->parser, $this->lex, $this->template);
unset($this->parser->root_buffer, $this->parser->current_buffer, $this->parser, $this->lex);
self::$_tag_objects = array();
// return compiled code to template object
$merged_code = '';
if (!$this->suppressMergedTemplates && !empty($this->merged_templates)) {
foreach ($this->merged_templates as $code) {
if (!empty($this->mergedSubTemplatesCode)) {
foreach ($this->mergedSubTemplatesCode as $code) {
$merged_code .= $code;
}
}
@ -306,20 +414,33 @@ abstract class Smarty_Internal_TemplateCompilerBase
$_compiled_code = Smarty_Internal_Filter_Handler::runFilter('post', $_compiled_code, $template);
}
if ($this->suppressTemplatePropertyHeader) {
$code = $_compiled_code . $merged_code;
$_compiled_code .= $merged_code;
} else {
$code = $template_header . $template->createTemplateCodeFrame($_compiled_code) . $merged_code;
$_compiled_code = $template_header . Smarty_Internal_Extension_CodeFrame::create($template, $_compiled_code) . $merged_code;
}
if (!empty($this->templateFunctionCode)) {
// run postfilter if required on compiled template code
if ((isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post'])) && !$this->suppressFilter) {
$_compiled_code .= Smarty_Internal_Filter_Handler::runFilter('post', $this->templateFunctionCode, $template);
} else {
$_compiled_code .= $this->templateFunctionCode;
}
}
// unset content because template inheritance could have replace source with parent code
unset ($template->source->content);
return $code;
$this->parent_compiler = null;
$this->template = null;
return $_compiled_code;
}
/**
* Compile Tag
* This is a call back from the lexer/parser
* It executes the required compile plugin for the Smarty tag
*
* Save current prefix code
* Compile tag
* Merge tag prefix code with saved one
* (required nested tags in attributes)
*
* @param string $tag tag name
* @param array $args array with tag attributes
@ -331,6 +452,27 @@ abstract class Smarty_Internal_TemplateCompilerBase
*/
public function compileTag($tag, $args, $parameter = array())
{
$this->prefixCodeStack[] = $this->prefix_code;
$this->prefix_code = array();
$result = $this->compileTag2($tag, $args, $parameter);
$this->prefix_code = array_merge($this->prefix_code, array_pop($this->prefixCodeStack));
return $result;
}
/**
* Compile Tag
*
* @param string $tag tag name
* @param array $args array with tag attributes
* @param array $parameter array with compilation parameter
*
* @throws SmartyCompilerException
* @throws SmartyException
* @return string compiled code
*/
private function compileTag2($tag, $args, $parameter)
{
$plugin_type = '';
// $args contains the attributes parsed and compiled by the lexer/parser
// assume that tag does compile into code, but creates no HTML output
$this->has_code = true;
@ -340,14 +482,13 @@ abstract class Smarty_Internal_TemplateCompilerBase
$this->template->used_tags[] = array($tag, $args);
}
// check nocache option flag
if (in_array("'nocache'", $args) || in_array(array('nocache' => 'true'), $args)
|| in_array(array('nocache' => '"true"'), $args) || in_array(array('nocache' => "'true'"), $args)
if (in_array("'nocache'", $args) || in_array(array('nocache' => 'true'), $args) || in_array(array('nocache' => '"true"'), $args) || in_array(array('nocache' => "'true'"), $args)
) {
$this->tag_nocache = true;
}
// compile the smarty tag (required compile classes to compile the tag are autoloaded)
if (($_output = $this->callTagCompiler($tag, $args, $parameter)) === false) {
if (isset($this->smarty->template_functions[$tag])) {
if (isset($this->parent_compiler->templateProperties['tpl_function'][$tag])) {
// template defined by {template} tag
$args['_attr']['name'] = "'" . $tag . "'";
$_output = $this->callTagCompiler('call', $args, $parameter);
@ -381,8 +522,7 @@ abstract class Smarty_Internal_TemplateCompilerBase
// check if tag is a registered object
if (isset($this->smarty->registered_objects[$tag]) && isset($parameter['object_method'])) {
$method = $parameter['object_method'];
if (!in_array($method, $this->smarty->registered_objects[$tag][3]) &&
(empty($this->smarty->registered_objects[$tag][1]) || in_array($method, $this->smarty->registered_objects[$tag][1]))
if (!in_array($method, $this->smarty->registered_objects[$tag][3]) && (empty($this->smarty->registered_objects[$tag][1]) || in_array($method, $this->smarty->registered_objects[$tag][1]))
) {
return $this->callTagCompiler('private_object_function', $args, $parameter, $tag, $method);
} elseif (in_array($method, $this->smarty->registered_objects[$tag][3])) {
@ -548,6 +688,42 @@ abstract class Smarty_Internal_TemplateCompilerBase
}
}
/**
* compile variable
*
* @param string $variable
*
* @return string
*/
public function compileVariable($variable)
{
if (strpos($variable, '(') == 0) {
// not a variable variable
$var = trim($variable, '\'');
$this->tag_nocache = $this->tag_nocache | $this->template->getVariable($var, null, true, false)->nocache;
$this->template->properties['variables'][$var] = $this->tag_nocache | $this->nocache;
}
return '$_smarty_tpl->tpl_vars[' . $variable . ']->value';
}
/**
* This method is called from parser to process a text content section
* - remove text from inheritance child templates as they may generate output
* - strip text if strip is enabled
*
* @param string $text
*
* @return null|\Smarty_Internal_ParseTree_Text
*/
public function processText($text)
{
if ($this->parser->strip) {
return new Smarty_Internal_ParseTree_Text($this->parser, preg_replace($this->stripRegEx, '', $text));
} else {
return new Smarty_Internal_ParseTree_Text($this->parser, $text);
}
}
/**
* lazy loads internal compile plugin for tag and calls the compile method
* compile objects cached for reuse.
@ -564,22 +740,21 @@ abstract class Smarty_Internal_TemplateCompilerBase
*/
public function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null)
{
// re-use object if already exists
if (isset(self::$_tag_objects[$tag])) {
// check if tag allowed by security
if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) {
// re-use object if already exists
if (!isset(self::$_tag_objects[$tag])) {
// lazy load internal compiler plugin
$class_name = 'Smarty_Internal_Compile_' . $tag;
if ($this->smarty->loadPlugin($class_name)) {
self::$_tag_objects[$tag] = new $class_name;
} else {
return false;
}
}
// compile this tag
return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3);
}
// lazy load internal compiler plugin
$class_name = 'Smarty_Internal_Compile_' . $tag;
if ($this->smarty->loadPlugin($class_name)) {
// check if tag allowed by security
if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) {
// use plugin if found
self::$_tag_objects[$tag] = new $class_name;
// compile this tag
return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3);
}
}
// no internal compile plugin for this tag
return false;
}
@ -656,9 +831,7 @@ abstract class Smarty_Internal_TemplateCompilerBase
$callback = null;
$script = null;
$cacheable = true;
$result = call_user_func_array(
$this->smarty->default_plugin_handler_func, array($tag, $plugin_type, $this->template, &$callback, &$script, &$cacheable)
);
$result = call_user_func_array($this->smarty->default_plugin_handler_func, array($tag, $plugin_type, $this->template, &$callback, &$script, &$cacheable));
if ($result) {
$this->tag_nocache = $this->tag_nocache || !$cacheable;
if ($script !== null) {
@ -670,7 +843,7 @@ abstract class Smarty_Internal_TemplateCompilerBase
$this->template->required_plugins['compiled'][$tag][$plugin_type]['file'] = $script;
$this->template->required_plugins['compiled'][$tag][$plugin_type]['function'] = $callback;
}
include_once $script;
require_once $script;
} else {
$this->trigger_template_error("Default plugin handler: Returned script file \"{$script}\" for \"{$tag}\" not found");
}
@ -690,6 +863,25 @@ abstract class Smarty_Internal_TemplateCompilerBase
return false;
}
/**
* Append code segments and remove unneeded ?> <?php transitions
*
* @param string $left
* @param string $right
*
* @return string
*/
public function appendCode($left, $right)
{
if (preg_match('/\s*\?>\s*$/', $left) && preg_match('/^\s*<\?php\s+/', $right)) {
$left = preg_replace('/\s*\?>\s*$/', "\n", $left);
$left .= preg_replace('/^\s*<\?php\s+/', '', $right);
} else {
$left .= $right;
}
return $left;
}
/**
* Inject inline code for nocache template sections
* This method gets the content of each template element from the parser.
@ -706,8 +898,7 @@ abstract class Smarty_Internal_TemplateCompilerBase
// If the template is not evaluated and we have a nocache section and or a nocache tag
if ($is_code && !empty($content)) {
// generate replacement code
if ((!($this->template->source->recompiled) || $this->forceNocache) && $this->template->caching && !$this->suppressNocacheProcessing &&
($this->nocache || $this->tag_nocache)
if ((!($this->template->source->recompiled) || $this->forceNocache) && $this->template->caching && !$this->suppressNocacheProcessing && ($this->nocache || $this->tag_nocache)
) {
$this->template->has_nocache_code = true;
$_output = addcslashes($content, '\'\\');
@ -732,13 +923,25 @@ abstract class Smarty_Internal_TemplateCompilerBase
return $_output;
}
/**
* Generate nocache code string
*
* @param string $code PHP code
*
* @return string
*/
public function makeNocacheCode($code)
{
return "echo '/*%%SmartyNocache:{$this->nocache_hash}%%*/<?php " . str_replace("^#^", "'", addcslashes($code, '\'\\')) . "?>/*/%%SmartyNocache:{$this->nocache_hash}%%*/';\n";
}
/**
* push current file and line offset on stack for tracing {block} source lines
*
* @param string $file new filename
* @param string $uid uid of file
* @param int $line line offset to source
* @param bool $debug false debug end_compile shall not be called
* @param string $file new filename
* @param string $uid uid of file
* @param int $line line offset to source
* @param bool $debug false debug end_compile shall not be called
*/
public function pushTrace($file, $uid, $line, $debug = true)
{
@ -756,7 +959,6 @@ abstract class Smarty_Internal_TemplateCompilerBase
/**
* restore file and line offset
*/
public function popTrace()
{
@ -797,6 +999,7 @@ abstract class Smarty_Internal_TemplateCompilerBase
// individual error message
$error_text .= $args;
} else {
$expect = array();
// expected token from parser
$error_text .= ' - Unexpected "' . $this->lex->value . '"';
if (count($this->parser->yy_get_expected_tokens($this->parser->yymajor)) <= 4) {

View File

@ -0,0 +1,571 @@
<?php
/**
* Smarty Internal TestInstall
* Test Smarty installation
*
* @package Smarty
* @subpackage Utilities
* @author Uwe Tews
*/
/**
* TestInstall class
*
* @package Smarty
* @subpackage Utilities
*/
class Smarty_Internal_TestInstall
{
/**
* diagnose Smarty setup
* If $errors is secified, the diagnostic report will be appended to the array, rather than being output.
*
* @param Smarty $smarty Smarty instance to test
* @param array $errors array to push results into rather than outputting them
*
* @return bool status, true if everything is fine, false else
*/
public static function testInstall(Smarty $smarty, &$errors = null)
{
$status = true;
if ($errors === null) {
echo "<PRE>\n";
echo "Smarty Installation test...\n";
echo "Testing template directory...\n";
}
$_stream_resolve_include_path = function_exists('stream_resolve_include_path');
// test if all registered template_dir are accessible
foreach ($smarty->getTemplateDir() as $template_dir) {
$_template_dir = $template_dir;
$template_dir = realpath($template_dir);
// resolve include_path or fail existence
if (!$template_dir) {
if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_template_dir)) {
// try PHP include_path
if ($_stream_resolve_include_path) {
$template_dir = stream_resolve_include_path($_template_dir);
} else {
$template_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_template_dir);
}
if ($template_dir !== false) {
if ($errors === null) {
echo "$template_dir is OK.\n";
}
continue;
} else {
$status = false;
$message = "FAILED: $_template_dir does not exist (and couldn't be found in include_path either)";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['template_dir'] = $message;
}
continue;
}
} else {
$status = false;
$message = "FAILED: $_template_dir does not exist";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['template_dir'] = $message;
}
continue;
}
}
if (!is_dir($template_dir)) {
$status = false;
$message = "FAILED: $template_dir is not a directory";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['template_dir'] = $message;
}
} elseif (!is_readable($template_dir)) {
$status = false;
$message = "FAILED: $template_dir is not readable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['template_dir'] = $message;
}
} else {
if ($errors === null) {
echo "$template_dir is OK.\n";
}
}
}
if ($errors === null) {
echo "Testing compile directory...\n";
}
// test if registered compile_dir is accessible
$__compile_dir = $smarty->getCompileDir();
$_compile_dir = realpath($__compile_dir);
if (!$_compile_dir) {
$status = false;
$message = "FAILED: {$__compile_dir} does not exist";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['compile_dir'] = $message;
}
} elseif (!is_dir($_compile_dir)) {
$status = false;
$message = "FAILED: {$_compile_dir} is not a directory";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['compile_dir'] = $message;
}
} elseif (!is_readable($_compile_dir)) {
$status = false;
$message = "FAILED: {$_compile_dir} is not readable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['compile_dir'] = $message;
}
} elseif (!is_writable($_compile_dir)) {
$status = false;
$message = "FAILED: {$_compile_dir} is not writable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['compile_dir'] = $message;
}
} else {
if ($errors === null) {
echo "{$_compile_dir} is OK.\n";
}
}
if ($errors === null) {
echo "Testing plugins directory...\n";
}
// test if all registered plugins_dir are accessible
// and if core plugins directory is still registered
$_core_plugins_dir = realpath(dirname(__FILE__) . '/../plugins');
$_core_plugins_available = false;
foreach ($smarty->getPluginsDir() as $plugin_dir) {
$_plugin_dir = $plugin_dir;
$plugin_dir = realpath($plugin_dir);
// resolve include_path or fail existence
if (!$plugin_dir) {
if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) {
// try PHP include_path
if ($_stream_resolve_include_path) {
$plugin_dir = stream_resolve_include_path($_plugin_dir);
} else {
$plugin_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_plugin_dir);
}
if ($plugin_dir !== false) {
if ($errors === null) {
echo "$plugin_dir is OK.\n";
}
continue;
} else {
$status = false;
$message = "FAILED: $_plugin_dir does not exist (and couldn't be found in include_path either)";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['plugins_dir'] = $message;
}
continue;
}
} else {
$status = false;
$message = "FAILED: $_plugin_dir does not exist";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['plugins_dir'] = $message;
}
continue;
}
}
if (!is_dir($plugin_dir)) {
$status = false;
$message = "FAILED: $plugin_dir is not a directory";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['plugins_dir'] = $message;
}
} elseif (!is_readable($plugin_dir)) {
$status = false;
$message = "FAILED: $plugin_dir is not readable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['plugins_dir'] = $message;
}
} elseif ($_core_plugins_dir && $_core_plugins_dir == realpath($plugin_dir)) {
$_core_plugins_available = true;
if ($errors === null) {
echo "$plugin_dir is OK.\n";
}
} else {
if ($errors === null) {
echo "$plugin_dir is OK.\n";
}
}
}
if (!$_core_plugins_available) {
$status = false;
$message = "WARNING: Smarty's own libs/plugins is not available";
if ($errors === null) {
echo $message . ".\n";
} elseif (!isset($errors['plugins_dir'])) {
$errors['plugins_dir'] = $message;
}
}
if ($errors === null) {
echo "Testing cache directory...\n";
}
// test if all registered cache_dir is accessible
$__cache_dir = $smarty->getCacheDir();
$_cache_dir = realpath($__cache_dir);
if (!$_cache_dir) {
$status = false;
$message = "FAILED: {$__cache_dir} does not exist";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['cache_dir'] = $message;
}
} elseif (!is_dir($_cache_dir)) {
$status = false;
$message = "FAILED: {$_cache_dir} is not a directory";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['cache_dir'] = $message;
}
} elseif (!is_readable($_cache_dir)) {
$status = false;
$message = "FAILED: {$_cache_dir} is not readable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['cache_dir'] = $message;
}
} elseif (!is_writable($_cache_dir)) {
$status = false;
$message = "FAILED: {$_cache_dir} is not writable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['cache_dir'] = $message;
}
} else {
if ($errors === null) {
echo "{$_cache_dir} is OK.\n";
}
}
if ($errors === null) {
echo "Testing configs directory...\n";
}
// test if all registered config_dir are accessible
foreach ($smarty->getConfigDir() as $config_dir) {
$_config_dir = $config_dir;
$config_dir = realpath($config_dir);
// resolve include_path or fail existence
if (!$config_dir) {
if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_config_dir)) {
// try PHP include_path
if ($_stream_resolve_include_path) {
$config_dir = stream_resolve_include_path($_config_dir);
} else {
$config_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_config_dir);
}
if ($config_dir !== false) {
if ($errors === null) {
echo "$config_dir is OK.\n";
}
continue;
} else {
$status = false;
$message = "FAILED: $_config_dir does not exist (and couldn't be found in include_path either)";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['config_dir'] = $message;
}
continue;
}
} else {
$status = false;
$message = "FAILED: $_config_dir does not exist";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['config_dir'] = $message;
}
continue;
}
}
if (!is_dir($config_dir)) {
$status = false;
$message = "FAILED: $config_dir is not a directory";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['config_dir'] = $message;
}
} elseif (!is_readable($config_dir)) {
$status = false;
$message = "FAILED: $config_dir is not readable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['config_dir'] = $message;
}
} else {
if ($errors === null) {
echo "$config_dir is OK.\n";
}
}
}
if ($errors === null) {
echo "Testing sysplugin files...\n";
}
// test if sysplugins are available
$source = SMARTY_SYSPLUGINS_DIR;
if (is_dir($source)) {
$expected = array(
"smarty_cacheresource.php" => true,
"smarty_cacheresource_custom.php" => true,
"smarty_cacheresource_keyvaluestore.php" => true,
"smarty_data.php" => true,
"smarty_internal_cacheresource_file.php" => true,
"smarty_internal_compile_append.php" => true,
"smarty_internal_compile_assign.php" => true,
"smarty_internal_compile_block.php" => true,
"smarty_internal_compile_break.php" => true,
"smarty_internal_compile_call.php" => true,
"smarty_internal_compile_capture.php" => true,
"smarty_internal_compile_config_load.php" => true,
"smarty_internal_compile_continue.php" => true,
"smarty_internal_compile_debug.php" => true,
"smarty_internal_compile_eval.php" => true,
"smarty_internal_compile_extends.php" => true,
"smarty_internal_compile_for.php" => true,
"smarty_internal_compile_foreach.php" => true,
"smarty_internal_compile_function.php" => true,
"smarty_internal_compile_if.php" => true,
"smarty_internal_compile_include.php" => true,
"smarty_internal_compile_include_php.php" => true,
"smarty_internal_compile_insert.php" => true,
"smarty_internal_compile_ldelim.php" => true,
"smarty_internal_compile_nocache.php" => true,
"smarty_internal_compile_private_block_plugin.php" => true,
"smarty_internal_compile_private_function_plugin.php" => true,
"smarty_internal_compile_private_modifier.php" => true,
"smarty_internal_compile_private_object_block_function.php" => true,
"smarty_internal_compile_private_object_function.php" => true,
"smarty_internal_compile_private_print_expression.php" => true,
"smarty_internal_compile_private_registered_block.php" => true,
"smarty_internal_compile_private_registered_function.php" => true,
"smarty_internal_compile_private_special_variable.php" => true,
"smarty_internal_compile_rdelim.php" => true,
"smarty_internal_compile_section.php" => true,
"smarty_internal_compile_setfilter.php" => true,
"smarty_internal_compile_while.php" => true,
"smarty_internal_compilebase.php" => true,
"smarty_internal_config_file_compiler.php" => true,
"smarty_internal_configfilelexer.php" => true,
"smarty_internal_configfileparser.php" => true,
"smarty_internal_data.php" => true,
"smarty_internal_debug.php" => true,
"smarty_internal_extension_codeframe.php" => true,
"smarty_internal_extension_config.php" => true,
"smarty_internal_extension_defaulttemplatehandler.php" => true,
"smarty_internal_filter_handler.php" => true,
"smarty_internal_function_call_handler.php" => true,
"smarty_internal_get_include_path.php" => true,
"smarty_internal_nocache_insert.php" => true,
"smarty_internal_parsetree.php" => true,
"smarty_internal_parsetree_code.php" => true,
"smarty_internal_parsetree_dq.php" => true,
"smarty_internal_parsetree_dqcontent.php" => true,
"smarty_internal_parsetree_tag.php" => true,
"smarty_internal_parsetree_template.php" => true,
"smarty_internal_parsetree_text.php" => true,
"smarty_internal_resource_eval.php" => true,
"smarty_internal_resource_extends.php" => true,
"smarty_internal_resource_file.php" => true,
"smarty_internal_resource_php.php" => true,
"smarty_internal_resource_registered.php" => true,
"smarty_internal_resource_stream.php" => true,
"smarty_internal_resource_string.php" => true,
"smarty_internal_smartytemplatecompiler.php" => true,
"smarty_internal_template.php" => true,
"smarty_internal_templatebase.php" => true,
"smarty_internal_templatecompilerbase.php" => true,
"smarty_internal_templatelexer.php" => true,
"smarty_internal_templateparser.php" => true,
"smarty_internal_utility.php" => true,
"smarty_internal_write_file.php" => true,
"smarty_resource.php" => true,
"smarty_resource_custom.php" => true,
"smarty_resource_recompiled.php" => true,
"smarty_resource_uncompiled.php" => true,
"smarty_security.php" => true,
"smarty_template_cached.php" => true,
"smarty_template_compiled.php" => true,
"smarty_template_config.php" => true,
"smarty_template_source.php" => true,
"smarty_undefined_variable.php" => true,
"smarty_variable.php" => true,
"smartycompilerexception.php" => true,
"smartyexception.php" => true,
);
$iterator = new DirectoryIterator($source);
foreach ($iterator as $file) {
if (!$file->isDot()) {
$filename = $file->getFilename();
if (isset($expected[$filename])) {
unset($expected[$filename]);
}
}
}
if ($expected) {
$status = false;
$message = "FAILED: files missing from libs/sysplugins: " . join(', ', array_keys($expected));
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['sysplugins'] = $message;
}
} elseif ($errors === null) {
echo "... OK\n";
}
} else {
$status = false;
$message = "FAILED: " . SMARTY_SYSPLUGINS_DIR . ' is not a directory';
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['sysplugins_dir_constant'] = $message;
}
}
if ($errors === null) {
echo "Testing plugin files...\n";
}
// test if core plugins are available
$source = SMARTY_PLUGINS_DIR;
if (is_dir($source)) {
$expected = array(
"block.textformat.php" => true,
"function.counter.php" => true,
"function.cycle.php" => true,
"function.fetch.php" => true,
"function.html_checkboxes.php" => true,
"function.html_image.php" => true,
"function.html_options.php" => true,
"function.html_radios.php" => true,
"function.html_select_date.php" => true,
"function.html_select_time.php" => true,
"function.html_table.php" => true,
"function.mailto.php" => true,
"function.math.php" => true,
"modifier.capitalize.php" => true,
"modifier.date_format.php" => true,
"modifier.debug_print_var.php" => true,
"modifier.escape.php" => true,
"modifier.regex_replace.php" => true,
"modifier.replace.php" => true,
"modifier.spacify.php" => true,
"modifier.truncate.php" => true,
"modifiercompiler.cat.php" => true,
"modifiercompiler.count_characters.php" => true,
"modifiercompiler.count_paragraphs.php" => true,
"modifiercompiler.count_sentences.php" => true,
"modifiercompiler.count_words.php" => true,
"modifiercompiler.default.php" => true,
"modifiercompiler.escape.php" => true,
"modifiercompiler.from_charset.php" => true,
"modifiercompiler.indent.php" => true,
"modifiercompiler.lower.php" => true,
"modifiercompiler.noprint.php" => true,
"modifiercompiler.string_format.php" => true,
"modifiercompiler.strip.php" => true,
"modifiercompiler.strip_tags.php" => true,
"modifiercompiler.to_charset.php" => true,
"modifiercompiler.unescape.php" => true,
"modifiercompiler.upper.php" => true,
"modifiercompiler.wordwrap.php" => true,
"outputfilter.trimwhitespace.php" => true,
"shared.escape_special_chars.php" => true,
"shared.literal_compiler_param.php" => true,
"shared.make_timestamp.php" => true,
"shared.mb_str_replace.php" => true,
"shared.mb_unicode.php" => true,
"shared.mb_wordwrap.php" => true,
"variablefilter.htmlspecialchars.php" => true,
);
$iterator = new DirectoryIterator($source);
foreach ($iterator as $file) {
if (!$file->isDot()) {
$filename = $file->getFilename();
if (isset($expected[$filename])) {
unset($expected[$filename]);
}
}
}
if ($expected) {
$status = false;
$message = "FAILED: files missing from libs/plugins: " . join(', ', array_keys($expected));
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['plugins'] = $message;
}
} elseif ($errors === null) {
echo "... OK\n";
}
} else {
$status = false;
$message = "FAILED: " . SMARTY_PLUGINS_DIR . ' is not a directory';
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['plugins_dir_constant'] = $message;
}
}
if ($errors === null) {
echo "Tests complete.\n";
echo "</PRE>\n";
}
return $status;
}
}

View File

@ -192,7 +192,7 @@ class Smarty_Internal_Utility
public static function clearCompiledTemplate($resource_name, $compile_id, $exp_time, Smarty $smarty)
{
$_compile_dir = realpath($smarty->getCompileDir()) . '/';
if ($_compile_dir == '/') { //We should never want to delete this!
if ($_compile_dir == '/') { //We should never want to delete this!
return 0;
}
$_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null;
@ -300,541 +300,4 @@ class Smarty_Internal_Utility
return $template->used_tags;
}
/**
* diagnose Smarty setup
* If $errors is secified, the diagnostic report will be appended to the array, rather than being output.
*
* @param Smarty $smarty Smarty instance to test
* @param array $errors array to push results into rather than outputting them
*
* @return bool status, true if everything is fine, false else
*/
public static function testInstall(Smarty $smarty, &$errors = null)
{
$status = true;
if ($errors === null) {
echo "<PRE>\n";
echo "Smarty Installation test...\n";
echo "Testing template directory...\n";
}
$_stream_resolve_include_path = function_exists('stream_resolve_include_path');
// test if all registered template_dir are accessible
foreach ($smarty->getTemplateDir() as $template_dir) {
$_template_dir = $template_dir;
$template_dir = realpath($template_dir);
// resolve include_path or fail existence
if (!$template_dir) {
if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_template_dir)) {
// try PHP include_path
if ($_stream_resolve_include_path) {
$template_dir = stream_resolve_include_path($_template_dir);
} else {
$template_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_template_dir);
}
if ($template_dir !== false) {
if ($errors === null) {
echo "$template_dir is OK.\n";
}
continue;
} else {
$status = false;
$message = "FAILED: $_template_dir does not exist (and couldn't be found in include_path either)";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['template_dir'] = $message;
}
continue;
}
} else {
$status = false;
$message = "FAILED: $_template_dir does not exist";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['template_dir'] = $message;
}
continue;
}
}
if (!is_dir($template_dir)) {
$status = false;
$message = "FAILED: $template_dir is not a directory";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['template_dir'] = $message;
}
} elseif (!is_readable($template_dir)) {
$status = false;
$message = "FAILED: $template_dir is not readable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['template_dir'] = $message;
}
} else {
if ($errors === null) {
echo "$template_dir is OK.\n";
}
}
}
if ($errors === null) {
echo "Testing compile directory...\n";
}
// test if registered compile_dir is accessible
$__compile_dir = $smarty->getCompileDir();
$_compile_dir = realpath($__compile_dir);
if (!$_compile_dir) {
$status = false;
$message = "FAILED: {$__compile_dir} does not exist";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['compile_dir'] = $message;
}
} elseif (!is_dir($_compile_dir)) {
$status = false;
$message = "FAILED: {$_compile_dir} is not a directory";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['compile_dir'] = $message;
}
} elseif (!is_readable($_compile_dir)) {
$status = false;
$message = "FAILED: {$_compile_dir} is not readable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['compile_dir'] = $message;
}
} elseif (!is_writable($_compile_dir)) {
$status = false;
$message = "FAILED: {$_compile_dir} is not writable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['compile_dir'] = $message;
}
} else {
if ($errors === null) {
echo "{$_compile_dir} is OK.\n";
}
}
if ($errors === null) {
echo "Testing plugins directory...\n";
}
// test if all registered plugins_dir are accessible
// and if core plugins directory is still registered
$_core_plugins_dir = realpath(dirname(__FILE__) . '/../plugins');
$_core_plugins_available = false;
foreach ($smarty->getPluginsDir() as $plugin_dir) {
$_plugin_dir = $plugin_dir;
$plugin_dir = realpath($plugin_dir);
// resolve include_path or fail existence
if (!$plugin_dir) {
if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) {
// try PHP include_path
if ($_stream_resolve_include_path) {
$plugin_dir = stream_resolve_include_path($_plugin_dir);
} else {
$plugin_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_plugin_dir);
}
if ($plugin_dir !== false) {
if ($errors === null) {
echo "$plugin_dir is OK.\n";
}
continue;
} else {
$status = false;
$message = "FAILED: $_plugin_dir does not exist (and couldn't be found in include_path either)";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['plugins_dir'] = $message;
}
continue;
}
} else {
$status = false;
$message = "FAILED: $_plugin_dir does not exist";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['plugins_dir'] = $message;
}
continue;
}
}
if (!is_dir($plugin_dir)) {
$status = false;
$message = "FAILED: $plugin_dir is not a directory";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['plugins_dir'] = $message;
}
} elseif (!is_readable($plugin_dir)) {
$status = false;
$message = "FAILED: $plugin_dir is not readable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['plugins_dir'] = $message;
}
} elseif ($_core_plugins_dir && $_core_plugins_dir == realpath($plugin_dir)) {
$_core_plugins_available = true;
if ($errors === null) {
echo "$plugin_dir is OK.\n";
}
} else {
if ($errors === null) {
echo "$plugin_dir is OK.\n";
}
}
}
if (!$_core_plugins_available) {
$status = false;
$message = "WARNING: Smarty's own libs/plugins is not available";
if ($errors === null) {
echo $message . ".\n";
} elseif (!isset($errors['plugins_dir'])) {
$errors['plugins_dir'] = $message;
}
}
if ($errors === null) {
echo "Testing cache directory...\n";
}
// test if all registered cache_dir is accessible
$__cache_dir = $smarty->getCacheDir();
$_cache_dir = realpath($__cache_dir);
if (!$_cache_dir) {
$status = false;
$message = "FAILED: {$__cache_dir} does not exist";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['cache_dir'] = $message;
}
} elseif (!is_dir($_cache_dir)) {
$status = false;
$message = "FAILED: {$_cache_dir} is not a directory";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['cache_dir'] = $message;
}
} elseif (!is_readable($_cache_dir)) {
$status = false;
$message = "FAILED: {$_cache_dir} is not readable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['cache_dir'] = $message;
}
} elseif (!is_writable($_cache_dir)) {
$status = false;
$message = "FAILED: {$_cache_dir} is not writable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['cache_dir'] = $message;
}
} else {
if ($errors === null) {
echo "{$_cache_dir} is OK.\n";
}
}
if ($errors === null) {
echo "Testing configs directory...\n";
}
// test if all registered config_dir are accessible
foreach ($smarty->getConfigDir() as $config_dir) {
$_config_dir = $config_dir;
$config_dir = realpath($config_dir);
// resolve include_path or fail existence
if (!$config_dir) {
if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_config_dir)) {
// try PHP include_path
if ($_stream_resolve_include_path) {
$config_dir = stream_resolve_include_path($_config_dir);
} else {
$config_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_config_dir);
}
if ($config_dir !== false) {
if ($errors === null) {
echo "$config_dir is OK.\n";
}
continue;
} else {
$status = false;
$message = "FAILED: $_config_dir does not exist (and couldn't be found in include_path either)";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['config_dir'] = $message;
}
continue;
}
} else {
$status = false;
$message = "FAILED: $_config_dir does not exist";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['config_dir'] = $message;
}
continue;
}
}
if (!is_dir($config_dir)) {
$status = false;
$message = "FAILED: $config_dir is not a directory";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['config_dir'] = $message;
}
} elseif (!is_readable($config_dir)) {
$status = false;
$message = "FAILED: $config_dir is not readable";
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['config_dir'] = $message;
}
} else {
if ($errors === null) {
echo "$config_dir is OK.\n";
}
}
}
if ($errors === null) {
echo "Testing sysplugin files...\n";
}
// test if sysplugins are available
$source = SMARTY_SYSPLUGINS_DIR;
if (is_dir($source)) {
$expected = array(
"smarty_cacheresource.php" => true,
"smarty_cacheresource_custom.php" => true,
"smarty_cacheresource_keyvaluestore.php" => true,
"smarty_config_source.php" => true,
"smarty_internal_cacheresource_file.php" => true,
"smarty_internal_compile_append.php" => true,
"smarty_internal_compile_assign.php" => true,
"smarty_internal_compile_block.php" => true,
"smarty_internal_compile_break.php" => true,
"smarty_internal_compile_call.php" => true,
"smarty_internal_compile_capture.php" => true,
"smarty_internal_compile_config_load.php" => true,
"smarty_internal_compile_continue.php" => true,
"smarty_internal_compile_debug.php" => true,
"smarty_internal_compile_eval.php" => true,
"smarty_internal_compile_extends.php" => true,
"smarty_internal_compile_for.php" => true,
"smarty_internal_compile_foreach.php" => true,
"smarty_internal_compile_function.php" => true,
"smarty_internal_compile_if.php" => true,
"smarty_internal_compile_include.php" => true,
"smarty_internal_compile_include_php.php" => true,
"smarty_internal_compile_insert.php" => true,
"smarty_internal_compile_ldelim.php" => true,
"smarty_internal_compile_nocache.php" => true,
"smarty_internal_compile_private_block_plugin.php" => true,
"smarty_internal_compile_private_function_plugin.php" => true,
"smarty_internal_compile_private_modifier.php" => true,
"smarty_internal_compile_private_object_block_function.php" => true,
"smarty_internal_compile_private_object_function.php" => true,
"smarty_internal_compile_private_print_expression.php" => true,
"smarty_internal_compile_private_registered_block.php" => true,
"smarty_internal_compile_private_registered_function.php" => true,
"smarty_internal_compile_private_special_variable.php" => true,
"smarty_internal_compile_rdelim.php" => true,
"smarty_internal_compile_section.php" => true,
"smarty_internal_compile_setfilter.php" => true,
"smarty_internal_compile_while.php" => true,
"smarty_internal_compilebase.php" => true,
"smarty_internal_config.php" => true,
"smarty_internal_config_file_compiler.php" => true,
"smarty_internal_configfilelexer.php" => true,
"smarty_internal_configfileparser.php" => true,
"smarty_internal_data.php" => true,
"smarty_internal_debug.php" => true,
"smarty_internal_filter_handler.php" => true,
"smarty_internal_function_call_handler.php" => true,
"smarty_internal_get_include_path.php" => true,
"smarty_internal_nocache_insert.php" => true,
"smarty_internal_parsetree.php" => true,
"smarty_internal_resource_eval.php" => true,
"smarty_internal_resource_extends.php" => true,
"smarty_internal_resource_file.php" => true,
"smarty_internal_resource_registered.php" => true,
"smarty_internal_resource_stream.php" => true,
"smarty_internal_resource_string.php" => true,
"smarty_internal_smartytemplatecompiler.php" => true,
"smarty_internal_template.php" => true,
"smarty_internal_templatebase.php" => true,
"smarty_internal_templatecompilerbase.php" => true,
"smarty_internal_templatelexer.php" => true,
"smarty_internal_templateparser.php" => true,
"smarty_internal_utility.php" => true,
"smarty_internal_write_file.php" => true,
"smarty_resource.php" => true,
"smarty_resource_custom.php" => true,
"smarty_resource_recompiled.php" => true,
"smarty_resource_uncompiled.php" => true,
"smarty_security.php" => true,
);
$iterator = new DirectoryIterator($source);
foreach ($iterator as $file) {
if (!$file->isDot()) {
$filename = $file->getFilename();
if (isset($expected[$filename])) {
unset($expected[$filename]);
}
}
}
if ($expected) {
$status = false;
$message = "FAILED: files missing from libs/sysplugins: " . join(', ', array_keys($expected));
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['sysplugins'] = $message;
}
} elseif ($errors === null) {
echo "... OK\n";
}
} else {
$status = false;
$message = "FAILED: " . SMARTY_SYSPLUGINS_DIR . ' is not a directory';
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['sysplugins_dir_constant'] = $message;
}
}
if ($errors === null) {
echo "Testing plugin files...\n";
}
// test if core plugins are available
$source = SMARTY_PLUGINS_DIR;
if (is_dir($source)) {
$expected = array(
"block.textformat.php" => true,
"function.counter.php" => true,
"function.cycle.php" => true,
"function.fetch.php" => true,
"function.html_checkboxes.php" => true,
"function.html_image.php" => true,
"function.html_options.php" => true,
"function.html_radios.php" => true,
"function.html_select_date.php" => true,
"function.html_select_time.php" => true,
"function.html_table.php" => true,
"function.mailto.php" => true,
"function.math.php" => true,
"modifier.capitalize.php" => true,
"modifier.date_format.php" => true,
"modifier.debug_print_var.php" => true,
"modifier.escape.php" => true,
"modifier.regex_replace.php" => true,
"modifier.replace.php" => true,
"modifier.spacify.php" => true,
"modifier.truncate.php" => true,
"modifiercompiler.cat.php" => true,
"modifiercompiler.count_characters.php" => true,
"modifiercompiler.count_paragraphs.php" => true,
"modifiercompiler.count_sentences.php" => true,
"modifiercompiler.count_words.php" => true,
"modifiercompiler.default.php" => true,
"modifiercompiler.escape.php" => true,
"modifiercompiler.from_charset.php" => true,
"modifiercompiler.indent.php" => true,
"modifiercompiler.lower.php" => true,
"modifiercompiler.noprint.php" => true,
"modifiercompiler.string_format.php" => true,
"modifiercompiler.strip.php" => true,
"modifiercompiler.strip_tags.php" => true,
"modifiercompiler.to_charset.php" => true,
"modifiercompiler.unescape.php" => true,
"modifiercompiler.upper.php" => true,
"modifiercompiler.wordwrap.php" => true,
"outputfilter.trimwhitespace.php" => true,
"shared.escape_special_chars.php" => true,
"shared.literal_compiler_param.php" => true,
"shared.make_timestamp.php" => true,
"shared.mb_str_replace.php" => true,
"shared.mb_unicode.php" => true,
"shared.mb_wordwrap.php" => true,
"variablefilter.htmlspecialchars.php" => true,
);
$iterator = new DirectoryIterator($source);
foreach ($iterator as $file) {
if (!$file->isDot()) {
$filename = $file->getFilename();
if (isset($expected[$filename])) {
unset($expected[$filename]);
}
}
}
if ($expected) {
$status = false;
$message = "FAILED: files missing from libs/plugins: " . join(', ', array_keys($expected));
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['plugins'] = $message;
}
} elseif ($errors === null) {
echo "... OK\n";
}
} else {
$status = false;
$message = "FAILED: " . SMARTY_PLUGINS_DIR . ' is not a directory';
if ($errors === null) {
echo $message . ".\n";
} else {
$errors['plugins_dir_constant'] = $message;
}
}
if ($errors === null) {
echo "Tests complete.\n";
echo "</PRE>\n";
}
return $status;
}
}

View File

@ -25,7 +25,7 @@ class Smarty_Internal_Write_File
* @throws SmartyException
* @return boolean true
*/
public static function writeFile($_filepath, $_contents, Smarty $smarty)
public function writeFile($_filepath, $_contents, Smarty $smarty)
{
$_error_reporting = error_reporting();
error_reporting($_error_reporting & ~E_NOTICE & ~E_WARNING);
@ -55,7 +55,9 @@ class Smarty_Internal_Write_File
*/
if (Smarty::$_IS_WINDOWS) {
// remove original file
@unlink($_filepath);
if (is_file($_filepath)) {
@unlink($_filepath);
}
// rename tmp file
$success = @rename($_tmp_file, $_filepath);
} else {
@ -63,17 +65,17 @@ class Smarty_Internal_Write_File
$success = @rename($_tmp_file, $_filepath);
if (!$success) {
// remove original file
@unlink($_filepath);
if (is_file($_filepath)) {
@unlink($_filepath);
}
// rename tmp file
$success = @rename($_tmp_file, $_filepath);
}
}
if (!$success) {
error_reporting($_error_reporting);
throw new SmartyException("unable to write file {$_filepath}");
}
if ($smarty->_file_perms !== null) {
// set file permissions
chmod($_filepath, $smarty->_file_perms);

View File

@ -16,6 +16,25 @@
*/
abstract class Smarty_Resource
{
/**
* Source is bypassing compiler
*
* @var boolean
*/
public $uncompiled = false;
/**
* Source must be recompiled on every occasion
*
* @var boolean
*/
public $recompiled = false;
/**
* resource handler object
*
* @var Smarty_Resource
*/
public $handler = null;
/**
* cache for Smarty_Template_Source instances
*
@ -28,24 +47,18 @@ abstract class Smarty_Resource
* @var array
*/
public static $compileds = array();
/**
* cache for Smarty_Resource instances
*
* @var array
*/
public static $resources = array();
/**
* resource types provided by the core
*
* @var array
*/
protected static $sysplugins = array(
'file' => true,
'string' => true,
'extends' => true,
'stream' => true,
'eval' => true,
'php' => true
'file' => 'smarty_internal_resource_file.php',
'string' => 'smarty_internal_resource_string.php',
'extends' => 'smarty_internal_resource_extends.php',
'stream' => 'smarty_internal_resource_stream.php',
'eval' => 'smarty_internal_resource_eval.php',
'php' => 'smarty_internal_resource_php.php'
);
/**
@ -103,270 +116,19 @@ abstract class Smarty_Resource
*
* @param Smarty $smarty Smarty instance
* @param string $resource_name resource_name to make unique
* @param boolean $is_config flag for config resource
* @param boolean $isConfig flag for config resource
*
* @return string unique resource name
*/
protected function buildUniqueResourceName(Smarty $smarty, $resource_name, $is_config = false)
public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false)
{
if ($is_config) {
if ($isConfig) {
return get_class($this) . '#' . $smarty->joined_config_dir . '#' . $resource_name;
} else {
return get_class($this) . '#' . $smarty->joined_template_dir . '#' . $resource_name;
}
}
/**
* populate Compiled Object with compiled filepath
*
* @param Smarty_Template_Compiled $compiled compiled object
* @param Smarty_Internal_Template $_template template object
*/
public function populateCompiledFilepath(Smarty_Template_Compiled $compiled, Smarty_Internal_Template $_template)
{
$_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!', '_', $_template->compile_id) : null;
$_filepath = $compiled->source->uid;
// if use_sub_dirs, break file into directories
if ($_template->smarty->use_sub_dirs) {
$_filepath = substr($_filepath, 0, 2) . DS
. substr($_filepath, 2, 2) . DS
. substr($_filepath, 4, 2) . DS
. $_filepath;
}
$_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^';
if (isset($_compile_id)) {
$_filepath = $_compile_id . $_compile_dir_sep . $_filepath;
}
// caching token
if ($_template->caching) {
$_cache = '.cache';
} else {
$_cache = '';
}
$_compile_dir = $_template->smarty->getCompileDir();
// set basename if not specified
$_basename = $this->getBasename($compiled->source);
if ($_basename === null) {
$_basename = basename(preg_replace('![^\w\/]+!', '_', $compiled->source->name));
}
// separate (optional) basename by dot
if ($_basename) {
$_basename = '.' . $_basename;
}
$compiled->filepath = $_compile_dir . $_filepath . '.' . $compiled->source->type . $_basename . $_cache . '.php';
}
/**
* Normalize Paths "foo/../bar" to "bar"
*
* @param string $_path path to normalize
* @param boolean $ds respect windows directory separator
*
* @return string normalized path
*/
protected function normalizePath($_path, $ds = true)
{
if ($ds) {
// don't we all just love windows?
$_path = str_replace('\\', '/', $_path);
}
$offset = 0;
// resolve simples
$_path = preg_replace('#/\./(\./)*#', '/', $_path);
// resolve parents
while (true) {
$_parent = strpos($_path, '/../', $offset);
if (!$_parent) {
break;
} elseif ($_path[$_parent - 1] === '.') {
$offset = $_parent + 3;
continue;
}
$_pos = strrpos($_path, '/', $_parent - strlen($_path) - 1);
if ($_pos === false) {
// don't we all just love windows?
$_pos = $_parent;
}
$_path = substr_replace($_path, '', $_pos, $_parent + 3 - $_pos);
}
if ($ds && DS != '/') {
// don't we all just love windows?
$_path = str_replace('/', '\\', $_path);
}
return $_path;
}
/**
* build template filepath by traversing the template_dir array
*
* @param Smarty_Template_Source $source source object
* @param Smarty_Internal_Template $_template template object
*
* @return string fully qualified filepath
* @throws SmartyException if default template handler is registered but not callable
*/
protected function buildFilepath(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null)
{
$file = $source->name;
if ($source instanceof Smarty_Config_Source) {
$_directories = $source->smarty->getConfigDir();
$_default_handler = $source->smarty->default_config_handler_func;
} else {
$_directories = $source->smarty->getTemplateDir();
$_default_handler = $source->smarty->default_template_handler_func;
}
// go relative to a given template?
$_file_is_dotted = $file[0] == '.' && ($file[1] == '.' || $file[1] == '/' || $file[1] == "\\");
if ($_template && $_template->parent instanceof Smarty_Internal_Template && $_file_is_dotted) {
if ($_template->parent->source->type != 'file' && $_template->parent->source->type != 'extends' && !$_template->parent->allow_relative_path) {
throw new SmartyException("Template '{$file}' cannot be relative to template of resource type '{$_template->parent->source->type}'");
}
$file = dirname($_template->parent->source->filepath) . DS . $file;
$_file_exact_match = true;
if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) {
// the path gained from the parent template is relative to the current working directory
// as expansions (like include_path) have already been done
$file = getcwd() . DS . $file;
}
}
// resolve relative path
if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) {
// don't we all just love windows?
$_path = DS . trim($file, '/');
$_was_relative = true;
} else {
// don't we all just love windows?
$_path = str_replace('\\', '/', $file);
}
$_path = $this->normalizePath($_path, false);
if (DS != '/') {
// don't we all just love windows?
$_path = str_replace('/', '\\', $_path);
}
// revert to relative
if (isset($_was_relative)) {
$_path = substr($_path, 1);
}
// this is only required for directories
$file = rtrim($_path, '/\\');
// files relative to a template only get one shot
if (isset($_file_exact_match)) {
return $this->fileExists($source, $file) ? $file : false;
}
// template_dir index?
if (preg_match('#^\[(?P<key>[^\]]+)\](?P<file>.+)$#', $file, $match)) {
$_directory = null;
// try string indexes
if (isset($_directories[$match['key']])) {
$_directory = $_directories[$match['key']];
} elseif (is_numeric($match['key'])) {
// try numeric index
$match['key'] = (int) $match['key'];
if (isset($_directories[$match['key']])) {
$_directory = $_directories[$match['key']];
} else {
// try at location index
$keys = array_keys($_directories);
$_directory = $_directories[$keys[$match['key']]];
}
}
if ($_directory) {
$_file = substr($file, strpos($file, ']') + 1);
$_filepath = $_directory . $_file;
if ($this->fileExists($source, $_filepath)) {
return $_filepath;
}
}
}
$_stream_resolve_include_path = function_exists('stream_resolve_include_path');
// relative file name?
if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) {
foreach ($_directories as $_directory) {
$_filepath = $_directory . $file;
if ($this->fileExists($source, $_filepath)) {
return $this->normalizePath($_filepath);
}
if ($source->smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_directory)) {
// try PHP include_path
if ($_stream_resolve_include_path) {
$_filepath = stream_resolve_include_path($_filepath);
} else {
$_filepath = Smarty_Internal_Get_Include_Path::getIncludePath($_filepath);
}
if ($_filepath !== false) {
if ($this->fileExists($source, $_filepath)) {
return $this->normalizePath($_filepath);
}
}
}
}
}
// try absolute filepath
if ($this->fileExists($source, $file)) {
return $file;
}
// no tpl file found
if ($_default_handler) {
if (!is_callable($_default_handler)) {
if ($source instanceof Smarty_Config_Source) {
throw new SmartyException("Default config handler not callable");
} else {
throw new SmartyException("Default template handler not callable");
}
}
$_return = call_user_func_array($_default_handler,
array($source->type, $source->name, &$_content, &$_timestamp, $source->smarty));
if (is_string($_return)) {
$source->timestamp = @filemtime($_return);
$source->exists = !!$source->timestamp;
return $_return;
} elseif ($_return === true) {
$source->content = $_content;
$source->timestamp = $_timestamp;
$source->exists = true;
return $_filepath;
}
}
// give up
return false;
}
/**
* test is file exists and save timestamp
*
* @param Smarty_Template_Source $source source object
* @param string $file file name
*
* @return bool true if file exists
*/
protected function fileExists(Smarty_Template_Source $source, $file)
{
$source->timestamp = is_file($file) ? @filemtime($file) : false;
return $source->exists = !!$source->timestamp;
}
/**
* Determine basename for compiled filename
*
@ -374,7 +136,7 @@ abstract class Smarty_Resource
*
* @return string resource's basename
*/
protected function getBasename(Smarty_Template_Source $source)
public function getBasename(Smarty_Template_Source $source)
{
return null;
}
@ -399,15 +161,8 @@ abstract class Smarty_Resource
if (isset($smarty->registered_resources[$type])) {
if ($smarty->registered_resources[$type] instanceof Smarty_Resource) {
$smarty->_resource_handlers[$type] = $smarty->registered_resources[$type];
// note registered to smarty is not kept unique!
return $smarty->_resource_handlers[$type];
}
if (!isset(self::$resources['registered'])) {
self::$resources['registered'] = new Smarty_Internal_Resource_Registered();
}
if (!isset($smarty->_resource_handlers[$type])) {
$smarty->_resource_handlers[$type] = self::$resources['registered'];
} else {
$smarty->_resource_handlers[$type] = new Smarty_Internal_Resource_Registered();
}
return $smarty->_resource_handlers[$type];
@ -415,25 +170,18 @@ abstract class Smarty_Resource
// try sysplugins dir
if (isset(self::$sysplugins[$type])) {
if (!isset(self::$resources[$type])) {
$_resource_class = 'Smarty_Internal_Resource_' . ucfirst($type);
self::$resources[$type] = new $_resource_class();
$_resource_class = 'Smarty_Internal_Resource_' . ucfirst($type);
if (!class_exists($_resource_class, false)) {
require SMARTY_SYSPLUGINS_DIR . self::$sysplugins[$type];
}
return $smarty->_resource_handlers[$type] = self::$resources[$type];
return $smarty->_resource_handlers[$type] = new $_resource_class();
}
// try plugins dir
$_resource_class = 'Smarty_Resource_' . ucfirst($type);
if ($smarty->loadPlugin($_resource_class)) {
if (isset(self::$resources[$type])) {
return $smarty->_resource_handlers[$type] = self::$resources[$type];
}
if (class_exists($_resource_class, false)) {
self::$resources[$type] = new $_resource_class();
return $smarty->_resource_handlers[$type] = self::$resources[$type];
return $smarty->_resource_handlers[$type] = new $_resource_class();
} else {
$smarty->registerResource($type, array(
"smarty_resource_{$type}_source",
@ -441,7 +189,6 @@ abstract class Smarty_Resource
"smarty_resource_{$type}_secure",
"smarty_resource_{$type}_trusted"
));
// give it another try, now that the resource is registered properly
return self::load($smarty, $type);
}
@ -454,11 +201,7 @@ abstract class Smarty_Resource
if (is_object($smarty->security_policy)) {
$smarty->security_policy->isTrustedStream($type);
}
if (!isset(self::$resources['stream'])) {
self::$resources['stream'] = new Smarty_Internal_Resource_Stream();
}
return $smarty->_resource_handlers[$type] = self::$resources['stream'];
return $smarty->_resource_handlers[$type] = new Smarty_Internal_Resource_Stream();;
}
// TODO: try default_(template|config)_handler
@ -473,23 +216,22 @@ abstract class Smarty_Resource
*
* @param string $resource_name template_resource or config_resource to parse
* @param string $default_resource the default resource_type defined in $smarty
* @param string &$name the parsed resource name
* @param string &$type the parsed resource type
*
* @return void
* @return array with parsed resource name and type
*/
protected static function parseResourceName($resource_name, $default_resource, &$name, &$type)
public static function parseResourceName($resource_name, $default_resource)
{
$parts = explode(':', $resource_name, 2);
if (!isset($parts[1]) || !isset($parts[0][1])) {
if (preg_match('/^([A-Za-z0-9_\-]{2,})[:]/', $resource_name, $match)) {
$type = $match[1];
$name = substr($resource_name, strlen($match[0]));
} else {
// no resource given, use default
// or single character before the colon is not a resource type, but part of the filepath
$type = $default_resource;
$name = $resource_name;
} else {
$type = $parts[0];
$name = $parts[1];
}
return array($name, $type);
}
/**
@ -511,19 +253,21 @@ abstract class Smarty_Resource
*/
public static function getUniqueTemplateName($template, $template_resource)
{
self::parseResourceName($template_resource, $template->smarty->default_resource_type, $name, $type);
$smarty = isset($template->smarty) ? $template->smarty : $template;
list($name, $type) = self::parseResourceName($template_resource, $smarty->default_resource_type);
// TODO: optimize for Smarty's internal resource types
$resource = Smarty_Resource::load($template->smarty, $type);
$resource = Smarty_Resource::load($smarty, $type);
// go relative to a given template?
$_file_is_dotted = $name[0] == '.' && ($name[1] == '.' || $name[1] == '/' || $name[1] == "\\");
$_file_is_dotted = $name[0] == '.' && ($name[1] == '.' || $name[1] == '/');
if ($template instanceof Smarty_Internal_Template && $_file_is_dotted && ($template->source->type == 'file' || $template->parent->source->type == 'extends')) {
$name = dirname($template->source->filepath) . DS . $name;
}
return $resource->buildUniqueResourceName($template->smarty, $name);
return $resource->buildUniqueResourceName($smarty, $name);
}
/**
* initialize Source Object for given resource
* wrapper for backward compatibility to versions < 3.1.22
* Either [$_template] or [$smarty, $template_resource] must be specified
*
* @param Smarty_Internal_Template $_template template object
@ -534,379 +278,7 @@ abstract class Smarty_Resource
*/
public static function source(Smarty_Internal_Template $_template = null, Smarty $smarty = null, $template_resource = null)
{
if ($_template) {
$smarty = $_template->smarty;
$template_resource = $_template->template_resource;
}
// parse resource_name, load resource handler, identify unique resource name
self::parseResourceName($template_resource, $smarty->default_resource_type, $name, $type);
$resource = Smarty_Resource::load($smarty, $type);
// go relative to a given template?
$_file_is_dotted = isset($name[0]) && $name[0] == '.' && ($name[1] == '.' || $name[1] == '/' || $name[1] == "\\");
if ($_file_is_dotted && isset($_template) && $_template->parent instanceof Smarty_Internal_Template && ($_template->parent->source->type == 'file' || $_template->parent->source->type == 'extends')) {
$name2 = dirname($_template->parent->source->filepath) . DS . $name;
} else {
$name2 = $name;
}
$unique_resource_name = $resource->buildUniqueResourceName($smarty, $name2);
// check runtime cache
$_cache_key = 'template|' . $unique_resource_name;
if ($smarty->compile_id) {
$_cache_key .= '|' . $smarty->compile_id;
}
if (isset(self::$sources[$_cache_key])) {
return self::$sources[$_cache_key];
}
// create source
$source = new Smarty_Template_Source($resource, $smarty, $template_resource, $type, $name, $unique_resource_name);
$resource->populate($source, $_template);
// runtime cache
self::$sources[$_cache_key] = $source;
return $source;
}
/**
* initialize Config Source Object for given resource
*
* @param Smarty_Internal_Config $_config config object
*
* @throws SmartyException
* @return Smarty_Config_Source Source Object
*/
public static function config(Smarty_Internal_Config $_config)
{
static $_incompatible_resources = array('eval' => true, 'string' => true, 'extends' => true, 'php' => true);
$config_resource = $_config->config_resource;
$smarty = $_config->smarty;
// parse resource_name
self::parseResourceName($config_resource, $smarty->default_config_type, $name, $type);
// make sure configs are not loaded via anything smarty can't handle
if (isset($_incompatible_resources[$type])) {
throw new SmartyException ("Unable to use resource '{$type}' for config");
}
// load resource handler, identify unique resource name
$resource = Smarty_Resource::load($smarty, $type);
$unique_resource_name = $resource->buildUniqueResourceName($smarty, $name, true);
// check runtime cache
$_cache_key = 'config|' . $unique_resource_name;
if (isset(self::$sources[$_cache_key])) {
return self::$sources[$_cache_key];
}
// create source
$source = new Smarty_Config_Source($resource, $smarty, $config_resource, $type, $name, $unique_resource_name);
$resource->populate($source, null);
// runtime cache
self::$sources[$_cache_key] = $source;
return $source;
return Smarty_Template_Source::load($_template, $smarty, $template_resource);
}
}
/**
* Smarty Resource Data Object
* Meta Data Container for Template Files
*
* @package Smarty
* @subpackage TemplateResources
* @author Rodney Rehm
* @property integer $timestamp Source Timestamp
* @property boolean $exists Source Existence
* @property boolean $template Extended Template reference
* @property string $content Source Content
*/
class Smarty_Template_Source
{
/**
* Name of the Class to compile this resource's contents with
*
* @var string
*/
public $compiler_class = null;
/**
* Name of the Class to tokenize this resource's contents with
*
* @var string
*/
public $template_lexer_class = null;
/**
* Name of the Class to parse this resource's contents with
*
* @var string
*/
public $template_parser_class = null;
/**
* Unique Template ID
*
* @var string
*/
public $uid = null;
/**
* Template Resource (Smarty_Internal_Template::$template_resource)
*
* @var string
*/
public $resource = null;
/**
* Resource Type
*
* @var string
*/
public $type = null;
/**
* Resource Name
*
* @var string
*/
public $name = null;
/**
* Unique Resource Name
*
* @var string
*/
public $unique_resource = null;
/**
* Source Filepath
*
* @var string
*/
public $filepath = null;
/**
* Source is bypassing compiler
*
* @var boolean
*/
public $uncompiled = null;
/**
* Source must be recompiled on every occasion
*
* @var boolean
*/
public $recompiled = null;
/**
* The Components an extended template is made of
*
* @var array
*/
public $components = null;
/**
* Resource Handler
*
* @var Smarty_Resource
*/
public $handler = null;
/**
* Smarty instance
*
* @var Smarty
*/
public $smarty = null;
/**
* create Source Object container
*
* @param Smarty_Resource $handler Resource Handler this source object communicates with
* @param Smarty $smarty Smarty instance this source object belongs to
* @param string $resource full template_resource
* @param string $type type of resource
* @param string $name resource name
* @param string $unique_resource unique resource name
*/
public function __construct(Smarty_Resource $handler, Smarty $smarty, $resource, $type, $name, $unique_resource)
{
$this->handler = $handler; // Note: prone to circular references
$this->compiler_class = $handler->compiler_class;
$this->template_lexer_class = $handler->template_lexer_class;
$this->template_parser_class = $handler->template_parser_class;
$this->uncompiled = $this->handler instanceof Smarty_Resource_Uncompiled;
$this->recompiled = $this->handler instanceof Smarty_Resource_Recompiled;
$this->smarty = $smarty;
$this->resource = $resource;
$this->type = $type;
$this->name = $name;
$this->unique_resource = $unique_resource;
}
/**
* get a Compiled Object of this source
*
* @param Smarty_Internal_Template|Smarty_Internal_Config $_template template object
*
* @return Smarty_Template_Compiled compiled object
*/
public function getCompiled($_template)
{
// check runtime cache
$_cache_key = $this->unique_resource . '#' . $_template->compile_id;
if (isset(Smarty_Resource::$compileds[$_cache_key])) {
return Smarty_Resource::$compileds[$_cache_key];
}
$compiled = new Smarty_Template_Compiled($this);
$this->handler->populateCompiledFilepath($compiled, $_template);
$compiled->timestamp = @filemtime($compiled->filepath);
$compiled->exists = !!$compiled->timestamp;
// runtime cache
Smarty_Resource::$compileds[$_cache_key] = $compiled;
return $compiled;
}
/**
* render the uncompiled source
*
* @param Smarty_Internal_Template $_template template object
*/
public function renderUncompiled(Smarty_Internal_Template $_template)
{
return $this->handler->renderUncompiled($this, $_template);
}
/**
* <<magic>> Generic Setter.
*
* @param string $property_name valid: timestamp, exists, content, template
* @param mixed $value new value (is not checked)
*
* @throws SmartyException if $property_name is not valid
*/
public function __set($property_name, $value)
{
switch ($property_name) {
// regular attributes
case 'timestamp':
case 'exists':
case 'content':
// required for extends: only
case 'template':
$this->$property_name = $value;
break;
default:
throw new SmartyException("invalid source property '$property_name'.");
}
}
/**
* <<magic>> Generic getter.
*
* @param string $property_name valid: timestamp, exists, content
*
* @return mixed
* @throws SmartyException if $property_name is not valid
*/
public function __get($property_name)
{
switch ($property_name) {
case 'timestamp':
case 'exists':
$this->handler->populateTimestamp($this);
return $this->$property_name;
case 'content':
return $this->content = $this->handler->getContent($this);
default:
throw new SmartyException("source property '$property_name' does not exist.");
}
}
}
/**
* Smarty Resource Data Object
* Meta Data Container for Template Files
*
* @package Smarty
* @subpackage TemplateResources
* @author Rodney Rehm
* @property string $content compiled content
*/
class Smarty_Template_Compiled
{
/**
* Compiled Filepath
*
* @var string
*/
public $filepath = null;
/**
* Compiled Timestamp
*
* @var integer
*/
public $timestamp = null;
/**
* Compiled Existence
*
* @var boolean
*/
public $exists = false;
/**
* Compiled Content Loaded
*
* @var boolean
*/
public $loaded = false;
/**
* Template was compiled
*
* @var boolean
*/
public $isCompiled = false;
/**
* Source Object
*
* @var Smarty_Template_Source
*/
public $source = null;
/**
* Metadata properties
* populated by Smarty_Internal_Template::decodeProperties()
*
* @var array
*/
public $_properties = null;
/**
* create Compiled Object container
*
* @param Smarty_Template_Source $source source object this compiled object belongs to
*/
public function __construct(Smarty_Template_Source $source)
{
$this->source = $source;
}
}

View File

@ -88,7 +88,7 @@ abstract class Smarty_Resource_Custom extends Smarty_Resource
*
* @return string resource's basename
*/
protected function getBasename(Smarty_Template_Source $source)
public function getBasename(Smarty_Template_Source $source)
{
return basename($source->name);
}

View File

@ -16,6 +16,13 @@
*/
abstract class Smarty_Resource_Recompiled extends Smarty_Resource
{
/**
* Flag that it's an recompiled resource
*
* @var bool
*/
public $recompiled = true;
/**
* populate Compiled Object with compiled filepath
*

View File

@ -16,6 +16,13 @@
*/
abstract class Smarty_Resource_Uncompiled extends Smarty_Resource
{
/**
* Flag that it's an uncompiled resource
*
* @var bool
*/
public $uncompiled = true;
/**
* Render and output the template (without using the compiler)
*
@ -38,4 +45,28 @@ abstract class Smarty_Resource_Uncompiled extends Smarty_Resource
$compiled->timestamp = false;
$compiled->exists = false;
}
/**
* render compiled template code
*
* @param Smarty_Internal_Template $_template
*
* @return string
* @throws Exception
*/
public function render($_template)
{
$level = ob_get_level();
ob_start();
try {
$this->renderUncompiled($_template->source, $_template);
return ob_get_clean();
}
catch (Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
throw $e;
}
}
}

View File

@ -54,6 +54,12 @@ class Smarty_Security
* @var array
*/
public $trusted_uri = array();
/**
* List of trusted constants names
*
* @var array
*/
public $trusted_constants = array();
/**
* This is an array of trusted static classes.
* If empty access to all static classes is allowed.
@ -62,6 +68,34 @@ class Smarty_Security
* @var array
*/
public $static_classes = array();
/**
* This is an nested array of trusted classes and static methods.
* If empty access to all static classes and methods is allowed.
* Format:
* array (
* 'class_1' => array('method_1', 'method_2'), // allowed methods listed
* 'class_2' => array(), // all methods of class allowed
* )
* If set to null none is allowed.
*
* @var array
*/
public $trusted_static_methods = array();
/**
* This is an array of trusted static properties.
* If empty access to all static classes and properties is allowed.
* Format:
* array (
* 'class_1' => array('prop_1', 'prop_2'), // allowed properties listed
* 'class_2' => array(), // all properties of class allowed
* )
* If set to null none is allowed.
*
* @var array
*/
public $trusted_static_properties = array();
/**
* This is an array of trusted PHP functions.
* If empty all functions are allowed.
@ -74,7 +108,6 @@ class Smarty_Security
'count', 'sizeof',
'in_array', 'is_array',
'time',
'nl2br',
);
/**
* This is an array of trusted PHP modifiers.
@ -85,7 +118,8 @@ class Smarty_Security
*/
public $php_modifiers = array(
'escape',
'count'
'count',
'nl2br',
);
/**
* This is an array of allowed tags.
@ -115,6 +149,12 @@ class Smarty_Security
* @var array
*/
public $disabled_modifiers = array();
/**
* This is an array of disabled special $smarty variables.
*
* @var array
*/
public $disabled_special_smarty_vars = array();
/**
* This is an array of trusted streams.
* If empty all streams are allowed.
@ -135,7 +175,18 @@ class Smarty_Security
* @var boolean
*/
public $allow_super_globals = true;
/**
* max template nesting level
*
* @var int
*/
public $max_template_nesting = 0;
/**
* current template nesting level
*
* @var int
*/
private $_current_template_nesting = 0;
/**
* Cache for $resource_dir lookup
*
@ -221,6 +272,46 @@ class Smarty_Security
return false; // should not, but who knows what happens to the compiler in the future?
}
/**
* Check if static class method/property is trusted.
*
* @param string $class_name
* @param string $params
* @param object $compiler compiler object
*
* @return boolean true if class method is trusted
* @throws SmartyCompilerException if static class method is not trusted
*/
public function isTrustedStaticClassAccess($class_name, $params, $compiler)
{
if (!isset($params[2])) {
// fall back
return $this->isTrustedStaticClass($class_name, $compiler);
}
if ($params[2] == 'method') {
$allowed = $this->trusted_static_methods;
$name = substr($params[0], 0, strpos($params[0], '('));
} else {
$allowed = $this->trusted_static_properties;
// strip '$'
$name = substr($params[0], 1);
}
if (isset($allowed)) {
if (empty($allowed)) {
// fall back
return $this->isTrustedStaticClass($class_name, $compiler);
}
if (isset($allowed[$class_name])
&& (empty($allowed[$class_name])
|| in_array($name, $allowed[$class_name]))
) {
return true;
}
}
$compiler->trigger_template_error("access to static class '{$class_name}' {$params[2]} '{$name}' not allowed by security setting");
return false; // should not, but who knows what happens to the compiler in the future?
}
/**
* Check if PHP modifier is trusted.
*
@ -274,6 +365,26 @@ class Smarty_Security
return false; // should not, but who knows what happens to the compiler in the future?
}
/**
* Check if special $smarty variable is trusted.
*
* @param string $var_name
* @param object $compiler compiler object
*
* @return boolean true if tag is trusted
* @throws SmartyCompilerException if modifier is not trusted
*/
public function isTrustedSpecialSmartyVar($var_name, $compiler)
{
if (!in_array($var_name, $this->disabled_special_smarty_vars)) {
return true;
} else {
$compiler->trigger_template_error("special variable '\$smarty.{$var_name}' not allowed by security setting", $compiler->lex->taglineno);
}
return false; // should not, but who knows what happens to the compiler in the future?
}
/**
* Check if modifier plugin is trusted.
*
@ -305,6 +416,33 @@ class Smarty_Security
return false; // should not, but who knows what happens to the compiler in the future?
}
/**
* Check if constants are enabled or trusted
*
* @param string $const contant name
* @param object $compiler compiler object
*
* @return bool
*/
public function isTrustedConstant($const, $compiler)
{
if (in_array($const, array('true', 'false', 'null'))) {
return true;
}
if (!empty($this->trusted_constants)) {
if (!in_array($const, $this->trusted_constants)) {
$compiler->trigger_template_error("Security: access to constant '{$const}' not permitted");
return false;
}
return true;
}
if ($this->allow_constants) {
return true;
}
$compiler->trigger_template_error("Security: access to constants not permitted");
return false;
}
/**
* Check if stream is trusted.
*
@ -477,4 +615,30 @@ class Smarty_Security
throw new SmartyException("directory '{$_filepath}' not allowed by security setting");
}
/**
* Start template processing
*
* @param $template
*
* @throws SmartyException
*/
public function startTemplate($template)
{
if ($this->max_template_nesting > 0 && $this->_current_template_nesting ++ >= $this->max_template_nesting) {
throw new SmartyException("maximum template nesting level of '{$this->max_template_nesting}' exceeded when calling '{$template->template_resource}'");
}
}
/**
* Exit template processing
*
* @param $template
*/
public function exitTemplate($template)
{
if ($this->max_template_nesting > 0) {
$this->_current_template_nesting --;
}
}
}

View File

@ -0,0 +1,403 @@
<?php
/**
* Created by PhpStorm.
* User: Uwe Tews
* Date: 04.12.2014
* Time: 06:08
*/
/**
* Smarty Resource Data Object
* Cache Data Container for Template Files
*
* @package Smarty
* @subpackage TemplateResources
* @author Rodney Rehm
*/
class Smarty_Template_Cached
{
/**
* Source Filepath
*
* @var string
*/
public $filepath = false;
/**
* Source Content
*
* @var string
*/
public $content = null;
/**
* Source Timestamp
*
* @var integer
*/
public $timestamp = false;
/**
* Source Existence
*
* @var boolean
*/
public $exists = false;
/**
* Cache Is Valid
*
* @var boolean
*/
public $valid = null;
/**
* Cache was processed
*
* @var boolean
*/
public $processed = false;
/**
* CacheResource Handler
*
* @var Smarty_CacheResource
*/
public $handler = null;
/**
* Template Compile Id (Smarty_Internal_Template::$compile_id)
*
* @var string
*/
public $compile_id = null;
/**
* Template Cache Id (Smarty_Internal_Template::$cache_id)
*
* @var string
*/
public $cache_id = null;
/**
* Id for cache locking
*
* @var string
*/
public $lock_id = null;
/**
* flag that cache is locked by this instance
*
* @var bool
*/
public $is_locked = false;
/**
* Source Object
*
* @var Smarty_Template_Source
*/
public $source = null;
/**
* create Cached Object container
*
* @param Smarty_Internal_Template $_template template object
*/
public function __construct(Smarty_Internal_Template $_template)
{
$this->compile_id = $_template->compile_id;
$this->cache_id = $_template->cache_id;
if (!isset($_template->source)) {
$_template->loadSource();
}
$this->source = $_template->source;
if (!class_exists('Smarty_CacheResource', false)) {
require SMARTY_SYSPLUGINS_DIR . 'smarty_cacheresource.php';
}
$this->handler = Smarty_CacheResource::load($_template->smarty);
}
/**
* @param Smarty_Internal_Template $_template
*
* @return Smarty_Template_Cached
*/
static function load(Smarty_Internal_Template $_template)
{
$_template->cached = $cached = new Smarty_Template_Cached($_template);
$cached->handler->populate($cached, $_template);
// caching enabled ?
if (!($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || $_template->caching == Smarty::CACHING_LIFETIME_SAVED) || $_template->source->recompiled) {
$cached->valid = false;
}
return $cached;
}
/**
* Check if cache is valid, lock cache if required
*
* @param \Smarty_Internal_Template $_template
*
* @return bool flag true if cache is valid
*/
public function isCached(Smarty_Internal_Template $_template)
{
if ($this->valid !== null) {
return $this->valid;
}
while (true) {
while (true) {
if ($this->exists === false || $_template->smarty->force_compile || $_template->smarty->force_cache) {
$this->valid = false;
} else {
$this->valid = true;
}
if ($this->valid && $_template->caching == Smarty::CACHING_LIFETIME_CURRENT && $_template->cache_lifetime >= 0 && time() > ($this->timestamp + $_template->cache_lifetime)) {
// lifetime expired
$this->valid = false;
}
if ($this->valid && $_template->source->timestamp > $this->timestamp) {
$this->valid = false;
}
if ($this->valid || !$_template->smarty->cache_locking) {
break;
}
if (!$this->handler->locked($_template->smarty, $this)) {
$this->handler->acquireLock($_template->smarty, $this);
break 2;
}
$this->handler->populate($this, $_template);
}
if ($this->valid) {
if (!$_template->smarty->cache_locking || $this->handler->locked($_template->smarty, $this) === null) {
// load cache file for the following checks
if ($_template->smarty->debugging) {
Smarty_Internal_Debug::start_cache($_template);
}
if ($this->handler->process($_template, $this) === false) {
$this->valid = false;
} else {
$this->processed = true;
}
if ($_template->smarty->debugging) {
Smarty_Internal_Debug::end_cache($_template);
}
} else {
$this->is_locked = true;
continue;
}
} else {
return $this->valid;
}
if ($this->valid && $_template->caching === Smarty::CACHING_LIFETIME_SAVED && $_template->properties['cache_lifetime'] >= 0 && (time() > ($_template->cached->timestamp + $_template->properties['cache_lifetime']))) {
$this->valid = false;
}
if ($_template->smarty->cache_locking) {
if (!$this->valid) {
$this->handler->acquireLock($_template->smarty, $this);
} elseif ($this->is_locked) {
$this->handler->releaseLock($_template->smarty, $this);
}
}
return $this->valid;
}
return $this->valid;
}
/**
* Process cached template
*
* @param Smarty_Internal_Template $_template template object
*/
public function process(Smarty_Internal_Template $_template)
{
if ($this->handler->process($_template, $this) === false) {
$this->valid = false;
}
if ($this->valid) {
$this->processed = true;
} else {
$this->processed = false;
}
}
/**
* Render cached template
*
* @param Smarty_Internal_Template $_template
*
* @return string
* @throws Exception
*/
public function render(Smarty_Internal_Template $_template)
{
if (!$this->processed) {
$this->process($_template);
}
return $_template->getRenderedTemplateCode();
}
/**
* Write this cache object to handler
*
* @param Smarty_Internal_Template $_template template object
* @param string $content content to cache
*
* @return boolean success
*/
public function write(Smarty_Internal_Template $_template, $content)
{
if (!$_template->source->recompiled) {
if ($this->handler->writeCachedContent($_template, $content)) {
$this->content = null;
$this->timestamp = time();
$this->exists = true;
$this->valid = true;
$this->processed = false;
if ($_template->smarty->cache_locking) {
$this->handler->releaseLock($_template->smarty, $this);
}
return true;
}
$this->content = null;
$this->timestamp = false;
$this->exists = false;
$this->valid = false;
$this->processed = false;
}
return false;
}
/**
* Read cache content from handler
*
* @param Smarty_Internal_Template $_template template object
*
* @return string content
*/
public function read(Smarty_Internal_Template $_template)
{
if (!$_template->source->recompiled) {
return $this->handler->readCachedContent($_template);
}
return false;
}
/**
* Sanitize content and write it to cache resource
*
* @param Smarty_Internal_Template $_template
* @param string $content
* @param bool $no_output_filter
*
* @throws SmartyException
*/
public function updateCache(Smarty_Internal_Template $_template, $content, $no_output_filter)
{
$_template->properties['has_nocache_code'] = false;
// get text between non-cached items
$cache_split = preg_split("!/\*%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!s", $content);
// get non-cached items
preg_match_all("!/\*%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!s", $content, $cache_parts);
$output = '';
// loop over items, stitch back together
foreach ($cache_split as $curr_idx => $curr_split) {
// escape PHP tags in template content
$output .= preg_replace('/(<%|%>|<\?php|<\?|\?>|<script\s+language\s*=\s*[\"\']?\s*php\s*[\"\']?\s*>)/', "<?php echo '\$1'; ?>\n", $curr_split);
if (isset($cache_parts[0][$curr_idx])) {
$_template->properties['has_nocache_code'] = true;
$output .= $cache_parts[1][$curr_idx];
}
}
if (!$no_output_filter && !$_template->has_nocache_code && (isset($_template->smarty->autoload_filters['output']) || isset($_template->smarty->registered_filters['output']))) {
$output = Smarty_Internal_Filter_Handler::runFilter('output', $output, $_template);
}
// write cache file content
$this->writeCachedContent($_template, $output);
}
/**
* Writes the content to cache resource
*
* @param Smarty_Internal_Template $_template
* @param string $content
*
* @return bool
*/
public function writeCachedContent(Smarty_Internal_Template $_template, $content)
{
if ($_template->source->recompiled || !($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || $_template->caching == Smarty::CACHING_LIFETIME_SAVED)) {
// don't write cache file
return false;
}
$_template->properties['cache_lifetime'] = $_template->cache_lifetime;
$_template->properties['unifunc'] = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
$content = Smarty_Internal_Extension_CodeFrame::create($_template, $content, true);
if (!empty($_template->properties['tpl_function'])) {
foreach ($_template->properties['tpl_function'] as $funcParam) {
if (is_file($funcParam['compiled_filepath'])) {
// read compiled file
$code = file_get_contents($funcParam['compiled_filepath']);
// grab template function
if (preg_match("/\/\* {$funcParam['call_name']} \*\/([\S\s]*?)\/\*\/ {$funcParam['call_name']} \*\//", $code, $match)) {
unset($code);
$content .= "<?php " . $match[0] . "?>\n";
}
}
}
}
return $this->write($_template, $content);
}
/**
* check client side cache
*
* @param Smarty_Internal_Template $_template
* @param string $content
*/
public function cacheModifiedCheck(Smarty_Internal_Template $_template, $content)
{
$_isCached = $_template->isCached() && !$_template->has_nocache_code;
$_last_modified_date = @substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);
if ($_isCached && $this->timestamp <= strtotime($_last_modified_date)) {
switch (PHP_SAPI) {
case 'cgi': // php-cgi < 5.3
case 'cgi-fcgi': // php-cgi >= 5.3
case 'fpm-fcgi': // php-fpm >= 5.3.3
header('Status: 304 Not Modified');
break;
case 'cli':
if ( /* ^phpunit */
!empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS']) /* phpunit$ */
) {
$_SERVER['SMARTY_PHPUNIT_HEADERS'][] = '304 Not Modified';
}
break;
default:
header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
break;
}
} else {
switch (PHP_SAPI) {
case 'cli':
if ( /* ^phpunit */
!empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS']) /* phpunit$ */
) {
$_SERVER['SMARTY_PHPUNIT_HEADERS'][] = 'Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->timestamp) . ' GMT';
}
break;
default:
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $this->timestamp) . ' GMT');
break;
}
echo $content;
}
}
}

View File

@ -0,0 +1,288 @@
<?php
/**
* Smarty Resource Data Object
* Meta Data Container for Template Files
*
* @package Smarty
* @subpackage TemplateResources
* @author Rodney Rehm
* @property string $content compiled content
*/
class Smarty_Template_Compiled
{
/**
* Compiled Filepath
*
* @var string
*/
public $filepath = null;
/**
* Compiled Timestamp
*
* @var integer
*/
public $timestamp = null;
/**
* Compiled Existence
*
* @var boolean
*/
public $exists = false;
/**
* Compiled Content Loaded
*
* @var boolean
*/
public $processed = false;
/**
* Code of recompiled template resource
*
* @var string|null
*/
public $code = null;
/**
* create Compiled Object container
*/
public function __construct()
{
}
/**
* get a Compiled Object of this source
*
* @param Smarty_Internal_Template $_template template object
*
* @return Smarty_Template_Compiled compiled object
*/
static function load($_template)
{
if (!isset($_template->source)) {
$_template->loadSource();
}
// check runtime cache
if (!$_template->source->recompiled && $_template->smarty->resource_caching) {
$_cache_key = $_template->source->unique_resource . '#';
if ($_template->caching) {
$_cache_key .= 'caching#';
}
$_cache_key .= $_template->compile_id;
if (isset($_template->source->compileds[$_cache_key])) {
return $_template->source->compileds[$_cache_key];
}
}
$compiled = new Smarty_Template_Compiled();
if (method_exists($_template->source->handler, 'populateCompiledFilepath')) {
$_template->source->handler->populateCompiledFilepath($compiled, $_template);
} else {
$compiled->populateCompiledFilepath($_template);
}
// runtime cache
if (!$_template->source->recompiled && $_template->smarty->resource_caching) {
$_template->source->compileds[$_cache_key] = $compiled;
}
return $compiled;
}
/**
* populate Compiled Object with compiled filepath
*
* @param Smarty_Internal_Template $_template template object
**/
public function populateCompiledFilepath(Smarty_Internal_Template $_template)
{
$_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!', '_', $_template->compile_id) : null;
if ($_template->source->isConfig) {
$_flag = '_' . ((int) $_template->smarty->config_read_hidden + (int) $_template->smarty->config_booleanize * 2
+ (int) $_template->smarty->config_overwrite * 4);
} else {
$_flag = '_' . ((int) $_template->smarty->merge_compiled_includes + (int) $_template->smarty->escape_html * 2);
}
$_filepath = $_template->source->uid . $_flag;
// if use_sub_dirs, break file into directories
if ($_template->smarty->use_sub_dirs) {
$_filepath = substr($_filepath, 0, 2) . DS
. substr($_filepath, 2, 2) . DS
. substr($_filepath, 4, 2) . DS
. $_filepath;
}
$_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^';
if (isset($_compile_id)) {
$_filepath = $_compile_id . $_compile_dir_sep . $_filepath;
}
// caching token
if ($_template->caching) {
$_cache = '.cache';
} else {
$_cache = '';
}
$_compile_dir = $_template->smarty->getCompileDir();
// set basename if not specified
$_basename = $_template->source->handler->getBasename($_template->source);
if ($_basename === null) {
$_basename = basename(preg_replace('![^\w\/]+!', '_', $_template->source->name));
}
// separate (optional) basename by dot
if ($_basename) {
$_basename = '.' . $_basename;
}
$this->filepath = $_compile_dir . $_filepath . '.' . $_template->source->type . $_basename . $_cache . '.php';
$this->timestamp = $this->exists = is_file($this->filepath);
if ($this->exists) {
$this->timestamp = @filemtime($this->filepath);
}
}
/**
* load compiled template or compile from source
*
* @param Smarty_Internal_Template $_template
*
* @throws Exception
*/
public function process(Smarty_Internal_Template $_template)
{
$_smarty_tpl = $_template;
if ($_template->source->recompiled || !$_template->compiled->exists || $_template->smarty->force_compile) {
$this->compileTemplateSource($_template);
$compileCheck = $_template->smarty->compile_check;
$_template->smarty->compile_check = false;
if ($_template->source->recompiled) {
$level = ob_get_level();
ob_start();
try {
eval("?>" . $this->code);
}
catch (Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
throw $e;
}
ob_get_clean();
$this->code = null;
} else {
include($_template->compiled->filepath);
}
$_template->smarty->compile_check = $compileCheck;
} else {
include($_template->compiled->filepath);
if ($_template->mustCompile) {
$this->compileTemplateSource($_template);
$compileCheck = $_template->smarty->compile_check;
$_template->smarty->compile_check = false;
include($_template->compiled->filepath);
$_template->smarty->compile_check = $compileCheck;
}
}
$this->unifunc = $_template->properties['unifunc'];
$this->processed = true;
}
/**
* render compiled template code
*
* @param Smarty_Internal_Template $_template
*
* @return string
* @throws Exception
*/
public function render(Smarty_Internal_Template $_template)
{
if (!$this->processed) {
$this->process($_template);
}
$_template->properties['unifunc'] = $this->unifunc;
return $_template->getRenderedTemplateCode();
}
/**
* compile template from source
*
* @param Smarty_Internal_Template $_template
*
* @return string
* @throws Exception
*/
public function compileTemplateSource(Smarty_Internal_Template $_template)
{
if (!$_template->source->recompiled) {
$_template->properties['file_dependency'] = array();
}
// compile locking
if (!$_template->source->recompiled) {
if ($saved_timestamp = $_template->compiled->timestamp) {
touch($_template->compiled->filepath);
}
}
// call compiler
try {
$code = $_template->compiler->compileTemplate($_template);
}
catch (Exception $e) {
// restore old timestamp in case of error
if (!$_template->source->recompiled && $saved_timestamp) {
touch($_template->compiled->filepath, $saved_timestamp);
}
throw $e;
}
// compiling succeeded
if ($_template->compiler->write_compiled_code) {
// write compiled template
$this->write($_template, $code);
$code = '';
}
// release compiler object to free memory
unset($_template->compiler);
return $code;
}
/**
* Write compiled code by handler
*
* @param Smarty_Internal_Template $_template template object
* @param string $code compiled code
*
* @return boolean success
*/
public function write(Smarty_Internal_Template $_template, $code)
{
if (!$_template->source->recompiled) {
$obj = new Smarty_Internal_Write_File();
if ($obj->writeFile($this->filepath, $code, $_template->smarty) === true) {
$this->timestamp = $this->exists = is_file($this->filepath);
if ($this->exists) {
$this->timestamp = @filemtime($this->filepath);
return true;
}
}
return false;
} else {
$this->code = $code;
}
$this->timestamp = time();
$this->exists = true;
return true;
}
/**
* Read compiled content from handler
*
* @param Smarty_Internal_Template $_template template object
*
* @return string content
*/
public function read(Smarty_Internal_Template $_template)
{
if (!$_template->source->recompiled) {
return file_get_contents($this->filepath);
}
return isset($this->content) ? $this->content : false;
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* Smarty Config Source Plugin
*
* @package Smarty
* @subpackage TemplateResources
* @author Uwe Tews
*/
/**
* Smarty Connfig Resource Data Object
* Meta Data Container for Template Files
*
* @package Smarty
* @subpackage TemplateResources
* @author Uwe Tews
* @property integer $timestamp Source Timestamp
* @property boolean $exists Source Existence
* @property boolean $template Extended Template reference
* @property string $content Source Content
*/
class Smarty_Template_Config extends Smarty_Template_Source
{
/**
* Name of the Class to compile this resource's contents with
*
* @var string
*/
public $compiler_class = 'Smarty_Internal_Config_File_Compiler';
/**
* Name of the Class to tokenize this resource's contents with
*
* @var string
*/
public $template_lexer_class = 'Smarty_Internal_Configfilelexer';
/**
* Name of the Class to parse this resource's contents with
*
* @var string
*/
public $template_parser_class = 'Smarty_Internal_Configfileparser';
/**
* array of section names, single section or null
*
* @var null|string|array
*/
public $config_sections = null;
/**
* scope into which the config variables shall be loaded
*
* @var string
*/
public $scope = 'local';
/**
* Flag that source is a config file
*
* @var bool
*/
public $isConfig = true;
/**
* create Source Object container
*
* @param Smarty_Resource $handler Resource Handler this source object communicates with
* @param Smarty $smarty Smarty instance this source object belongs to
* @param string $resource full template_resource
* @param string $type type of resource
* @param string $name resource name
*/
public function __construct(Smarty_Resource $handler, Smarty $smarty, $resource, $type, $name)
{
$this->handler = clone $handler; // Note: prone to circular references
$this->resource = $resource;
$this->type = $type;
$this->name = $name;
$this->smarty = $smarty;
}
/**
* initialize Source Object for given resource
* Either [$_template] or [$smarty, $template_resource] must be specified
*
* @param Smarty_Internal_Template $_template template object
* @param Smarty $smarty smarty object
* @param string $template_resource resource identifier
*
* @return Smarty_Template_Source Source Object
* @throws SmartyException
*/
public static function load(Smarty_Internal_Template $_template = null, Smarty $smarty = null, $template_resource = null)
{
static $_incompatible_resources = array('extends' => true, 'php' => true);
$smarty = $_template->smarty;
$template_resource = $_template->template_resource;
if (empty($template_resource)) {
throw new SmartyException('Missing config name');
}
// parse resource_name, load resource handler
list($name, $type) = Smarty_Resource::parseResourceName($template_resource, $smarty->default_config_type);
// make sure configs are not loaded via anything smarty can't handle
if (isset($_incompatible_resources[$type])) {
throw new SmartyException ("Unable to use resource '{$type}' for config");
}
$resource = Smarty_Resource::load($smarty, $type);
$source = new Smarty_Template_Config($resource, $smarty, $template_resource, $type, $name);
$resource->populate($source, $_template);
if ((!isset($source->exists) || !$source->exists) && isset($_template->smarty->default_config_handler_func)) {
Smarty_Internal_Extension_DefaultTemplateHandler::_getDefault($_template, $source, $resource);
}
$source->unique_resource = $resource->buildUniqueResourceName($smarty, $name, true);
return $source;
}
}

View File

@ -0,0 +1,285 @@
<?php
/**
* Smarty Resource Data Object
* Meta Data Container for Template Files
*
* @package Smarty
* @subpackage TemplateResources
* @author Rodney Rehm
* @property integer $timestamp Source Timestamp
* @property boolean $exists Source Existence
* @property boolean $template Extended Template reference
* @property string $content Source Content
*/
class Smarty_Template_Source
{
/**
* Name of the Class to compile this resource's contents with
*
* @var string
*/
public $compiler_class = null;
/**
* Name of the Class to tokenize this resource's contents with
*
* @var string
*/
public $template_lexer_class = null;
/**
* Name of the Class to parse this resource's contents with
*
* @var string
*/
public $template_parser_class = null;
/**
* Unique Template ID
*
* @var string
*/
public $uid = null;
/**
* Template Resource (Smarty_Internal_Template::$template_resource)
*
* @var string
*/
public $resource = null;
/**
* Resource Type
*
* @var string
*/
public $type = null;
/**
* Resource Name
*
* @var string
*/
public $name = null;
/**
* Unique Resource Name
*
* @var string
*/
public $unique_resource = null;
/**
* Source Filepath
*
* @var string
*/
public $filepath = null;
/**
* Source File Base name
*
* @var string
*/
public $basename = null;
/**
* The Components an extended template is made of
*
* @var array
*/
public $components = null;
/**
* Resource Handler
*
* @var Smarty_Resource
*/
public $handler = null;
/**
* Smarty instance
*
* @var Smarty
*/
public $smarty = null;
/**
* Resource is source
*
* @var bool
*/
public $isConfig = false;
/**
* Source is bypassing compiler
*
* @var boolean
*/
public $uncompiled = false;
/**
* Source must be recompiled on every occasion
*
* @var boolean
*/
public $recompiled = false;
/**
* cache for Smarty_Template_Compiled instances
*
* @var array
*/
public $compileds = array();
/**
* create Source Object container
*
* @param Smarty_Resource $handler Resource Handler this source object communicates with
* @param Smarty $smarty Smarty instance this source object belongs to
* @param string $resource full template_resource
* @param string $type type of resource
* @param string $name resource name
*
* @internal param string $unique_resource unique resource name
*/
public function __construct(Smarty_Resource $handler, Smarty $smarty, $resource, $type, $name)
{
$this->handler = $handler; // Note: prone to circular references
$this->recompiled = $handler->recompiled;
$this->uncompiled = $handler->uncompiled;
$this->compiler_class = $handler->compiler_class;
$this->template_lexer_class = $handler->template_lexer_class;
$this->template_parser_class = $handler->template_parser_class;
$this->smarty = $smarty;
$this->resource = $resource;
$this->type = $type;
$this->name = $name;
}
/**
* initialize Source Object for given resource
* Either [$_template] or [$smarty, $template_resource] must be specified
*
* @param Smarty_Internal_Template $_template template object
* @param Smarty $smarty smarty object
* @param string $template_resource resource identifier
*
* @return Smarty_Template_Source Source Object
* @throws SmartyException
*/
public static function load(Smarty_Internal_Template $_template = null, Smarty $smarty = null, $template_resource = null)
{
if ($_template) {
$smarty = $_template->smarty;
$template_resource = $_template->template_resource;
}
if (empty($template_resource)) {
throw new SmartyException('Missing template name');
}
// parse resource_name, load resource handler, identify unique resource name
list($name, $type) = Smarty_Resource::parseResourceName($template_resource, $smarty->default_resource_type);
$resource = Smarty_Resource::load($smarty, $type);
// if resource is not recompiling and resource name is not dotted we can check the source cache
if ($smarty->resource_caching && !$resource->recompiled && !(isset($name[1]) && $name[0] == '.' && ($name[1] == '.' || $name[1] == '/'))) {
$unique_resource = $resource->buildUniqueResourceName($smarty, $name);
if (isset($smarty->source_objects[$unique_resource])) {
return $smarty->source_objects[$unique_resource];
}
} else {
$unique_resource = null;
}
// create new source object
$source = new Smarty_Template_Source($resource, $smarty, $template_resource, $type, $name);
$resource->populate($source, $_template);
if ((!isset($source->exists) || !$source->exists) && isset($_template->smarty->default_template_handler_func)) {
Smarty_Internal_Extension_DefaultTemplateHandler::_getDefault($_template, $source, $resObj);
}
// on recompiling resources we are done
if ($smarty->resource_caching && !$resource->recompiled) {
// may by we have already $unique_resource
$is_relative = false;
if (!isset($unique_resource)) {
$is_relative = isset($name[1]) && $name[0] == '.' && ($name[1] == '.' || $name[1] == '/') &&
($type == 'file' || (isset($_template->parent->source) && $_template->parent->source->type == 'extends'));
$unique_resource = $resource->buildUniqueResourceName($smarty, $is_relative ? $source->filepath . $name : $name);
}
$source->unique_resource = $unique_resource;
// save in runtime cache if not relative
if (!$is_relative) {
$smarty->source_objects[$unique_resource] = $source;
}
}
return $source;
}
/**
* render the uncompiled source
*
* @param Smarty_Internal_Template $_template template object
*/
public function renderUncompiled(Smarty_Internal_Template $_template)
{
$level = ob_get_level();
ob_start();
try {
$this->handler->renderUncompiled($_template->source, $_template);
return ob_get_clean();
}
catch (Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
throw $e;
}
}
/**
* <<magic>> Generic Setter.
*
* @param string $property_name valid: timestamp, exists, content, template
* @param mixed $value new value (is not checked)
*
* @throws SmartyException if $property_name is not valid
*/
public function __set($property_name, $value)
{
switch ($property_name) {
// regular attributes
case 'timestamp':
case 'exists':
case 'content':
// required for extends: only
case 'template':
$this->$property_name = $value;
break;
default:
throw new SmartyException("source property '$property_name' does not exist.");
}
}
/**
* <<magic>> Generic getter.
*
* @param string $property_name valid: timestamp, exists, content
*
* @return mixed
* @throws SmartyException if $property_name is not valid
*/
public function __get($property_name)
{
switch ($property_name) {
case 'timestamp':
case 'exists':
$this->handler->populateTimestamp($this);
return $this->$property_name;
case 'content':
return $this->content = $this->handler->getContent($this);
default:
throw new SmartyException("source property '$property_name' does not exist.");
}
}
}

View File

@ -0,0 +1,37 @@
<?php
/**
* class for undefined variable object
* This class defines an object for undefined variable handling
*
* @package Smarty
* @subpackage Template
*/
class Smarty_Undefined_Variable
{
/**
* Returns FALSE for 'nocache' and NULL otherwise.
*
* @param string $name
*
* @return bool
*/
public function __get($name)
{
if ($name == 'nocache') {
return false;
} else {
return null;
}
}
/**
* Always returns an empty string.
*
* @return string
*/
public function __toString()
{
return "";
}
}

View File

@ -0,0 +1,55 @@
<?php
/**
* class for the Smarty variable object
* This class defines the Smarty variable object
*
* @package Smarty
* @subpackage Template
*/
class Smarty_Variable
{
/**
* template variable
*
* @var mixed
*/
public $value = null;
/**
* if true any output of this variable will be not cached
*
* @var boolean
*/
public $nocache = false;
/**
* the scope the variable will have (local,parent or root)
*
* @var int
*/
public $scope = Smarty::SCOPE_LOCAL;
/**
* create Smarty variable object
*
* @param mixed $value the value to assign
* @param boolean $nocache if true any output of this variable will be not cached
* @param int $scope the scope the variable will have (local,parent or root)
*/
public function __construct($value = null, $nocache = false, $scope = Smarty::SCOPE_LOCAL)
{
$this->value = $value;
$this->nocache = $nocache;
$this->scope = $scope;
}
/**
* <<magic>> String conversion
*
* @return string
*/
public function __toString()
{
return (string) $this->value;
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* Smarty compiler exception class
*
* @package Smarty
*/
class SmartyCompilerException extends SmartyException
{
public function __toString()
{
return ' --> Smarty Compiler: ' . $this->message . ' <-- ';
}
/**
* The line number of the template error
*
* @type int|null
*/
public $line = null;
/**
* The template source snippet relating to the error
*
* @type string|null
*/
public $source = null;
/**
* The raw text of the error message
*
* @type string|null
*/
public $desc = null;
/**
* The resource identifier or template name
*
* @type string|null
*/
public $template = null;
}

View File

@ -0,0 +1,15 @@
<?php
/**
* Smarty exception class
*
* @package Smarty
*/
class SmartyException extends Exception
{
public static $escape = false;
public function __toString()
{
return ' --> Smarty: ' . (self::$escape ? htmlentities($this->message) : $this->message) . ' <-- ';
}
}