From c23ce16cafb826c8bb4fe7aaf2a5525b29052b23 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sun, 6 Dec 2015 20:12:05 +0100 Subject: update smarty library - seems to bring some performance improvement --- library/Smarty/COMPOSER_RELEASE_NOTES.txt | 29 + library/Smarty/INHERITANCE_RELEASE_NOTES.txt | 35 + library/Smarty/NEW_FEATURES.txt | 86 + library/Smarty/README | 2 +- library/Smarty/README.md | 52 + library/Smarty/change_log.txt | 244 +- library/Smarty/demo/plugins/cacheresource.pdo.php | 322 ++ .../Smarty/demo/plugins/cacheresource.pdo_gzip.php | 43 + library/Smarty/demo/templates/header.tpl | 2 +- .../lexer/smarty_internal_configfilelexer.plex | 318 ++ .../lexer/smarty_internal_configfileparser.y | 362 ++ .../lexer/smarty_internal_templatelexer.plex | 770 +++ .../Smarty/lexer/smarty_internal_templateparser.y | 1329 ++++++ library/Smarty/libs/Autoloader.php | 158 + library/Smarty/libs/Smarty.class.php | 840 ++-- library/Smarty/libs/SmartyBC.class.php | 27 +- library/Smarty/libs/debug.tpl | 57 +- .../Smarty/libs/plugins/modifier.date_format.php | 2 +- .../libs/plugins/modifier.debug_print_var.php | 26 +- .../libs/plugins/outputfilter.trimwhitespace.php | 4 +- .../libs/sysplugins/smarty_cacheresource.php | 225 +- .../sysplugins/smarty_cacheresource_custom.php | 52 +- .../smarty_cacheresource_keyvaluestore.php | 35 +- .../libs/sysplugins/smarty_config_source.php | 94 - library/Smarty/libs/sysplugins/smarty_data.php | 66 + .../smarty_internal_cacheresource_file.php | 49 +- .../sysplugins/smarty_internal_compile_assign.php | 6 +- .../sysplugins/smarty_internal_compile_block.php | 23 +- .../sysplugins/smarty_internal_compile_call.php | 52 +- .../smarty_internal_compile_config_load.php | 3 +- .../sysplugins/smarty_internal_compile_for.php | 45 +- .../sysplugins/smarty_internal_compile_foreach.php | 151 +- .../smarty_internal_compile_function.php | 200 +- .../libs/sysplugins/smarty_internal_compile_if.php | 29 +- .../sysplugins/smarty_internal_compile_include.php | 217 +- .../sysplugins/smarty_internal_compile_insert.php | 20 +- .../sysplugins/smarty_internal_compile_nocache.php | 13 +- .../smarty_internal_compile_private_php.php | 197 + ...y_internal_compile_private_special_variable.php | 132 +- .../sysplugins/smarty_internal_compile_while.php | 9 +- .../libs/sysplugins/smarty_internal_config.php | 306 -- .../smarty_internal_config_file_compiler.php | 75 +- .../sysplugins/smarty_internal_configfilelexer.php | 399 +- .../smarty_internal_configfileparser.php | 710 ++- .../libs/sysplugins/smarty_internal_data.php | 242 +- .../libs/sysplugins/smarty_internal_debug.php | 314 +- .../smarty_internal_extension_codeframe.php | 127 + .../smarty_internal_extension_config.php | 160 + ...y_internal_extension_defaulttemplatehandler.php | 85 + .../smarty_internal_function_call_handler.php | 65 +- .../libs/sysplugins/smarty_internal_parsetree.php | 318 +- .../sysplugins/smarty_internal_parsetree_code.php | 42 + .../sysplugins/smarty_internal_parsetree_dq.php | 86 + .../smarty_internal_parsetree_dqcontent.php | 42 + .../sysplugins/smarty_internal_parsetree_tag.php | 66 + .../smarty_internal_parsetree_template.php | 98 + .../sysplugins/smarty_internal_parsetree_text.php | 40 + .../sysplugins/smarty_internal_resource_eval.php | 6 +- .../smarty_internal_resource_extends.php | 2 +- .../sysplugins/smarty_internal_resource_file.php | 149 +- .../sysplugins/smarty_internal_resource_php.php | 59 +- .../smarty_internal_resource_registered.php | 2 +- .../sysplugins/smarty_internal_resource_stream.php | 4 +- .../sysplugins/smarty_internal_resource_string.php | 6 +- .../smarty_internal_smartytemplatecompiler.php | 16 +- .../libs/sysplugins/smarty_internal_template.php | 736 +-- .../sysplugins/smarty_internal_templatebase.php | 1417 +++--- .../smarty_internal_templatecompilerbase.php | 331 +- .../sysplugins/smarty_internal_templatelexer.php | 1206 ++--- .../sysplugins/smarty_internal_templateparser.php | 5045 ++++++-------------- .../sysplugins/smarty_internal_testinstall.php | 571 +++ .../libs/sysplugins/smarty_internal_utility.php | 540 +-- .../libs/sysplugins/smarty_internal_write_file.php | 12 +- library/Smarty/libs/sysplugins/smarty_resource.php | 732 +-- .../libs/sysplugins/smarty_resource_custom.php | 2 +- .../libs/sysplugins/smarty_resource_recompiled.php | 7 + .../libs/sysplugins/smarty_resource_uncompiled.php | 31 + library/Smarty/libs/sysplugins/smarty_security.php | 170 +- .../libs/sysplugins/smarty_template_cached.php | 403 ++ .../libs/sysplugins/smarty_template_compiled.php | 288 ++ .../libs/sysplugins/smarty_template_config.php | 118 + .../libs/sysplugins/smarty_template_source.php | 285 ++ .../libs/sysplugins/smarty_undefined_variable.php | 37 + library/Smarty/libs/sysplugins/smarty_variable.php | 55 + .../libs/sysplugins/smartycompilerexception.php | 39 + library/Smarty/libs/sysplugins/smartyexception.php | 15 + 86 files changed, 12376 insertions(+), 9409 deletions(-) create mode 100644 library/Smarty/COMPOSER_RELEASE_NOTES.txt create mode 100644 library/Smarty/INHERITANCE_RELEASE_NOTES.txt create mode 100644 library/Smarty/NEW_FEATURES.txt create mode 100644 library/Smarty/README.md create mode 100644 library/Smarty/demo/plugins/cacheresource.pdo.php create mode 100644 library/Smarty/demo/plugins/cacheresource.pdo_gzip.php create mode 100644 library/Smarty/lexer/smarty_internal_configfilelexer.plex create mode 100644 library/Smarty/lexer/smarty_internal_configfileparser.y create mode 100644 library/Smarty/lexer/smarty_internal_templatelexer.plex create mode 100644 library/Smarty/lexer/smarty_internal_templateparser.y create mode 100644 library/Smarty/libs/Autoloader.php delete mode 100644 library/Smarty/libs/sysplugins/smarty_config_source.php create mode 100644 library/Smarty/libs/sysplugins/smarty_data.php create mode 100644 library/Smarty/libs/sysplugins/smarty_internal_compile_private_php.php delete mode 100644 library/Smarty/libs/sysplugins/smarty_internal_config.php create mode 100644 library/Smarty/libs/sysplugins/smarty_internal_extension_codeframe.php create mode 100644 library/Smarty/libs/sysplugins/smarty_internal_extension_config.php create mode 100644 library/Smarty/libs/sysplugins/smarty_internal_extension_defaulttemplatehandler.php create mode 100644 library/Smarty/libs/sysplugins/smarty_internal_parsetree_code.php create mode 100644 library/Smarty/libs/sysplugins/smarty_internal_parsetree_dq.php create mode 100644 library/Smarty/libs/sysplugins/smarty_internal_parsetree_dqcontent.php create mode 100644 library/Smarty/libs/sysplugins/smarty_internal_parsetree_tag.php create mode 100644 library/Smarty/libs/sysplugins/smarty_internal_parsetree_template.php create mode 100644 library/Smarty/libs/sysplugins/smarty_internal_parsetree_text.php create mode 100644 library/Smarty/libs/sysplugins/smarty_internal_testinstall.php create mode 100644 library/Smarty/libs/sysplugins/smarty_template_cached.php create mode 100644 library/Smarty/libs/sysplugins/smarty_template_compiled.php create mode 100644 library/Smarty/libs/sysplugins/smarty_template_config.php create mode 100644 library/Smarty/libs/sysplugins/smarty_template_source.php create mode 100644 library/Smarty/libs/sysplugins/smarty_undefined_variable.php create mode 100644 library/Smarty/libs/sysplugins/smarty_variable.php create mode 100644 library/Smarty/libs/sysplugins/smartycompilerexception.php create mode 100644 library/Smarty/libs/sysplugins/smartyexception.php (limited to 'library') diff --git a/library/Smarty/COMPOSER_RELEASE_NOTES.txt b/library/Smarty/COMPOSER_RELEASE_NOTES.txt new file mode 100644 index 000000000..c943d9f2e --- /dev/null +++ b/library/Smarty/COMPOSER_RELEASE_NOTES.txt @@ -0,0 +1,29 @@ + + +Starting with Smarty 3.1.21 Composer has been configured to load the packages from github. + +******************************************************************************* +* * +* NOTE: Because of this change you must clear your local composer cache with * +* the "composer clearcache" command * +* * +******************************************************************************* + +To get the latest stable version use + "require": { + "smarty/smarty": "~3.1" + } +in your composer.json file. + +To get the trunk version use + "require": { + "smarty/smarty": "~3.1@dev" + } + +The "smarty/smarty" package will start at libs/.... subfolder. + +To retrieve the development and documentation folders add + "require-dev": { + "smarty/smarty-dev": "~3.1@dev" + } + diff --git a/library/Smarty/INHERITANCE_RELEASE_NOTES.txt b/library/Smarty/INHERITANCE_RELEASE_NOTES.txt new file mode 100644 index 000000000..a7d285f0a --- /dev/null +++ b/library/Smarty/INHERITANCE_RELEASE_NOTES.txt @@ -0,0 +1,35 @@ +In Smarty 3.1 template inheritance is a compile time process. All the extending of {block} tags +is done at compile time and the parent and child templates are compiled in a single compiled template. +{include} subtemplate could also {block} tags. Such subtemplate could not compiled by it's own because +it could be used in other context where the {block} extended with a different result. For that reasion +the compiled code of {include} subtemplates gets also merged in compiled inheritance template. + +Merging the code into a single compile template has some drawbacks. +1. You could not use variable file names in {include} Smarty would use the {include} of compilation time. +2. You could not use individual compile_id in {include} +3. Seperate caching of subtemplate was not possible +4. Any change of the template directory structure between calls was not necessarily seen. + +Starting with 3.1.15 some of the above conditions got checked and resulted in an exception. It turned out +that a couple of users did use some of above and now got exceptions. + +To resolve this starting with 3.1.16 there is a new configuration parameter $inheritance_merge_compiled_includes. +For most backward compatibility its default setting is true. +With this setting all {include} subtemplate will be merge into the compiled inheritance template, but the above cases +could be rejected by exception. + + +If $smarty->inheritance_merge_compiled_includes = false; {include} subtemplate will not be merged. +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 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 = $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. + + +In the upcomming major release Smarty 3.2 inheritance will no longer be a compile time process. +All restrictions will be then removed. + diff --git a/library/Smarty/NEW_FEATURES.txt b/library/Smarty/NEW_FEATURES.txt new file mode 100644 index 000000000..b2c18c99b --- /dev/null +++ b/library/Smarty/NEW_FEATURES.txt @@ -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. + + . + \ No newline at end of file diff --git a/library/Smarty/README b/library/Smarty/README index 6367f030e..9304219b4 100644 --- a/library/Smarty/README +++ b/library/Smarty/README @@ -1,4 +1,4 @@ -Smarty 3.1.21 +Smarty 3.x Author: Monte Ohrt Author: Uwe Tews diff --git a/library/Smarty/README.md b/library/Smarty/README.md new file mode 100644 index 000000000..f5f93fa95 --- /dev/null +++ b/library/Smarty/README.md @@ -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 diff --git a/library/Smarty/change_log.txt b/library/Smarty/change_log.txt index a0161659d..5606b1d83 100644 --- a/library/Smarty/change_log.txt +++ b/library/Smarty/change_log.txt @@ -1,8 +1,242 @@ - ===== 3.1.22-dev ===== (xx.xx.2014) + ===== 3.1.27===== (18.06.2015) +18.06.2015 + - bugfix another update on file path normalization failed on path containing something like "/.foo/" https://github.com/smarty-php/smarty/issues/56 + + ===== 3.1.26===== (18.06.2015) +18.06.2015 + - bugfix file path normalization failed on path containing something like "/.foo/" https://github.com/smarty-php/smarty/issues/56 + +17.06.2015 + - bugfix calling a plugin with nocache option but no other attributes like {foo nocache} caused call to undefined function https://github.com/smarty-php/smarty/issues/55 + + ===== 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 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 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 ?> 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 +277,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 +966,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 diff --git a/library/Smarty/demo/plugins/cacheresource.pdo.php b/library/Smarty/demo/plugins/cacheresource.pdo.php new file mode 100644 index 000000000..569193aa4 --- /dev/null +++ b/library/Smarty/demo/plugins/cacheresource.pdo.php @@ -0,0 +1,322 @@ +setCachingType('pdo'); + * $smarty->loadPlugin('Smarty_CacheResource_Pdo'); + * $smarty->registerCacheResource('pdo', new Smarty_CacheResource_Pdo($cnx, 'smarty_cache')); + * + * @author Beno!t POLASZEK - 2014 + */ +class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom +{ + + protected $fetchStatements = Array('default' => 'SELECT %2$s + FROM %1$s + WHERE 1 + AND id = :id + AND cache_id IS NULL + AND compile_id IS NULL', + + 'withCacheId' => 'SELECT %2$s + FROM %1$s + WHERE 1 + AND id = :id + AND cache_id = :cache_id + AND compile_id IS NULL', + + 'withCompileId' => 'SELECT %2$s + FROM %1$s + WHERE 1 + AND id = :id + AND compile_id = :compile_id + AND cache_id IS NULL', + + 'withCacheIdAndCompileId' => 'SELECT %2$s + FROM %1$s + WHERE 1 + AND id = :id + AND cache_id = :cache_id + AND compile_id = :compile_id'); + protected $insertStatement = 'INSERT INTO %s + + SET id = :id, + name = :name, + cache_id = :cache_id, + compile_id = :compile_id, + modified = CURRENT_TIMESTAMP, + expire = DATE_ADD(CURRENT_TIMESTAMP, INTERVAL :expire SECOND), + content = :content + + ON DUPLICATE KEY UPDATE + name = :name, + cache_id = :cache_id, + compile_id = :compile_id, + modified = CURRENT_TIMESTAMP, + expire = DATE_ADD(CURRENT_TIMESTAMP, INTERVAL :expire SECOND), + content = :content'; + + protected $deleteStatement = 'DELETE FROM %1$s WHERE %2$s'; + protected $truncateStatement = 'TRUNCATE TABLE %s'; + + protected $fetchColumns = 'modified, content'; + protected $fetchTimestampColumns = 'modified'; + + protected $pdo, $table, $database; + + /* + * Constructor + * + * @param PDO $pdo PDO : active connection + * @param string $table : table (or view) name + * @param string $database : optionnal - if table is located in another db + */ + public function __construct(PDO $pdo, $table, $database = null) + { + + if (is_null($table)) { + throw new SmartyException("Table name for caching can't be null"); + } + + $this->pdo = $pdo; + $this->table = $table; + $this->database = $database; + + $this->fillStatementsWithTableName(); + } + + /* + * Fills the table name into the statements. + * + * @return Current Instance + * @access protected + */ + protected function fillStatementsWithTableName() + { + + foreach ($this->fetchStatements AS &$statement) { + $statement = sprintf($statement, $this->getTableName(), '%s'); + } + + $this->insertStatement = sprintf($this->insertStatement, $this->getTableName()); + $this->deleteStatement = sprintf($this->deleteStatement, $this->getTableName(), '%s'); + $this->truncateStatement = sprintf($this->truncateStatement, $this->getTableName()); + + return $this; + } + + /* + * Gets the fetch statement, depending on what you specify + * + * @param string $columns : the column(s) name(s) you want to retrieve from the database + * @param string $id unique cache content identifier + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id + * @access protected + */ + protected function getFetchStatement($columns, $id, $cache_id = null, $compile_id = null) + { + + if (!is_null($cache_id) && !is_null($compile_id)) { + $query = $this->fetchStatements['withCacheIdAndCompileId'] AND $args = Array('id' => $id, 'cache_id' => $cache_id, 'compile_id' => $compile_id); + } elseif (is_null($cache_id) && !is_null($compile_id)) { + $query = $this->fetchStatements['withCompileId'] AND $args = Array('id' => $id, 'compile_id' => $compile_id); + } elseif (!is_null($cache_id) && is_null($compile_id)) { + $query = $this->fetchStatements['withCacheId'] AND $args = Array('id' => $id, 'cache_id' => $cache_id); + } else { + $query = $this->fetchStatements['default'] AND $args = Array('id' => $id); + } + + $query = sprintf($query, $columns); + + $stmt = $this->pdo->prepare($query); + + foreach ($args AS $key => $value) { + $stmt->bindValue($key, $value); + } + + return $stmt; + } + + /** + * fetch cached content and its modification time from data source + * + * @param string $id unique cache content identifier + * @param string $name template name + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id + * @param string $content cached content + * @param integer $mtime cache modification timestamp (epoch) + * + * @return void + * @access protected + */ + protected function fetch($id, $name, $cache_id = null, $compile_id = null, &$content, &$mtime) + { + + $stmt = $this->getFetchStatement($this->fetchColumns, $id, $cache_id, $compile_id); + $stmt ->execute(); + $row = $stmt->fetch(); + $stmt ->closeCursor(); + + if ($row) { + $content = $this->outputContent($row['content']); + $mtime = strtotime($row['modified']); + } else { + $content = null; + $mtime = null; + } + } + + /** + * Fetch cached content's modification timestamp from data source + * {@internal implementing this method is optional. + * Only implement it if modification times can be accessed faster than loading the complete cached content.}} + * + * @param string $id unique cache content identifier + * @param string $name template name + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id + * + * @return integer|boolean timestamp (epoch) the template was modified, or false if not found + * @access protected + */ + // protected function fetchTimestamp($id, $name, $cache_id = null, $compile_id = null) { + // $stmt = $this->getFetchStatement($this->fetchTimestampColumns, $id, $cache_id, $compile_id); + // $stmt -> execute(); + // $mtime = strtotime($stmt->fetchColumn()); + // $stmt -> closeCursor(); + // return $mtime; + // } + + /** + * Save content to cache + * + * @param string $id unique cache content identifier + * @param string $name template name + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id + * @param integer|null $exp_time seconds till expiration time in seconds or null + * @param string $content content to cache + * + * @return boolean success + * @access protected + */ + protected function save($id, $name, $cache_id = null, $compile_id = null, $exp_time, $content) + { + + $stmt = $this->pdo->prepare($this->insertStatement); + + $stmt ->bindValue('id', $id); + $stmt ->bindValue('name', $name); + $stmt ->bindValue('cache_id', $cache_id, (is_null($cache_id)) ? PDO::PARAM_NULL : PDO::PARAM_STR); + $stmt ->bindValue('compile_id', $compile_id, (is_null($compile_id)) ? PDO::PARAM_NULL : PDO::PARAM_STR); + $stmt ->bindValue('expire', (int) $exp_time, PDO::PARAM_INT); + $stmt ->bindValue('content', $this->inputContent($content)); + $stmt ->execute(); + + return !!$stmt->rowCount(); + } + + /* + * Encodes the content before saving to database + * + * @param string $content + * @return string $content + * @access protected + */ + protected function inputContent($content) + { + return $content; + } + + /* + * Decodes the content before saving to database + * + * @param string $content + * @return string $content + * @access protected + */ + protected function outputContent($content) + { + return $content; + } + + /** + * Delete content from cache + * + * @param string|null $name template name + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id + * @param integer|null|-1 $exp_time seconds till expiration or null + * + * @return integer number of deleted caches + * @access protected + */ + protected function delete($name = null, $cache_id = null, $compile_id = null, $exp_time = null) + { + + // delete the whole cache + if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) { + // returning the number of deleted caches would require a second query to count them + $this->pdo->query($this->truncateStatement); + return - 1; + } + // build the filter + $where = array(); + // equal test name + if ($name !== null) { + $where[] = 'name = ' . $this->pdo->quote($name); + } + // equal test cache_id and match sub-groups + if ($cache_id !== null) { + $where[] = '(cache_id = ' . $this->pdo->quote($cache_id) + . ' OR cache_id LIKE ' . $this->pdo->quote($cache_id . '|%') . ')'; + } + // equal test compile_id + if ($compile_id !== null) { + $where[] = 'compile_id = ' . $this->pdo->quote($compile_id); + } + // for clearing expired caches + if ($exp_time === Smarty::CLEAR_EXPIRED) { + $where[] = 'expire < CURRENT_TIMESTAMP'; + } // range test expiration time + elseif ($exp_time !== null) { + $where[] = 'modified < DATE_SUB(NOW(), INTERVAL ' . intval($exp_time) . ' SECOND)'; + } + // run delete query + $query = $this->pdo->query(sprintf($this->deleteStatement, join(' AND ', $where))); + return $query->rowCount(); + } + + /** + * Gets the formatted table name + * + * @return string + * @access protected + */ + protected function getTableName() + { + return (is_null($this->database)) ? "`{$this->table}`" : "`{$this->database}`.`{$this->table}`"; + } +} + \ No newline at end of file diff --git a/library/Smarty/demo/plugins/cacheresource.pdo_gzip.php b/library/Smarty/demo/plugins/cacheresource.pdo_gzip.php new file mode 100644 index 000000000..8a9e0a5dd --- /dev/null +++ b/library/Smarty/demo/plugins/cacheresource.pdo_gzip.php @@ -0,0 +1,43 @@ +setCachingType('pdo_gzip'); + * $smarty->loadPlugin('Smarty_CacheResource_Pdo_Gzip'); + * $smarty->registerCacheResource('pdo_gzip', new Smarty_CacheResource_Pdo_Gzip($cnx, 'smarty_cache')); + * + * @require Smarty_CacheResource_Pdo class + * @author Beno!t POLASZEK - 2014 + */ +require_once 'cacheresource.pdo.php'; + +class Smarty_CacheResource_Pdo_Gzip extends Smarty_CacheResource_Pdo +{ + + /* + * Encodes the content before saving to database + * + * @param string $content + * @return string $content + * @access protected + */ + protected function inputContent($content) + { + return gzdeflate($content); + } + + /* + * Decodes the content before saving to database + * + * @param string $content + * @return string $content + * @access protected + */ + protected function outputContent($content) + { + return gzinflate($content); + } +} + \ No newline at end of file diff --git a/library/Smarty/demo/templates/header.tpl b/library/Smarty/demo/templates/header.tpl index 13fa6cb5a..783210a18 100644 --- a/library/Smarty/demo/templates/header.tpl +++ b/library/Smarty/demo/templates/header.tpl @@ -1,5 +1,5 @@ - {$title} - {$Name} +{$title} - {$Name} diff --git a/library/Smarty/lexer/smarty_internal_configfilelexer.plex b/library/Smarty/lexer/smarty_internal_configfilelexer.plex new file mode 100644 index 000000000..94196be5f --- /dev/null +++ b/library/Smarty/lexer/smarty_internal_configfilelexer.plex @@ -0,0 +1,318 @@ + '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 + ); + + /** + * 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); + $this->data = $data . "\n"; //now all lines are \n-terminated + $this->counter = 0; + if (preg_match('/^\xEF\xBB\xBF/', $this->data, $match)) { + $this->counter += strlen($match[0]); + } + $this->line = 1; + $this->compiler = $compiler; + $this->smarty = $compiler->smarty; + $this->configBooleanize = $this->smarty->config_booleanize; + } + + public static function &instance($new_instance = null) + { + static $instance = null; + if (isset($new_instance) && is_object($new_instance)) { + $instance = $new_instance; + } + return $instance; + } + + public function PrintTrace() + { + $this->yyTraceFILE = fopen('php://output', 'w'); + $this->yyTracePrompt = '
'; + } + + +/*!lex2php +%input $this->data +%counter $this->counter +%token $this->token +%value $this->value +%line $this->line +commentstart = /#|;/ +openB = /\[/ +closeB = /\]/ +section = /.*?(?=[\.=\[\]\r\n])/ +equal = /=/ +whitespace = /[ \t\r]+/ +dot = /\./ +id = /[0-9]*[a-zA-Z_]\w*/ +newline = /\n/ +single_quoted_string = /'[^'\\]*(?:\\.[^'\\]*)*'(?=[ \t\r]*[\n#;])/ +double_quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"(?=[ \t\r]*[\n#;])/ +tripple_quotes = /"""/ +tripple_quotes_end = /"""(?=[ \t\r]*[\n#;])/ +text = /[\S\s]/ +float = /\d+\.\d+(?=[ \t\r]*[\n#;])/ +int = /\d+(?=[ \t\r]*[\n#;])/ +maybe_bool = /[a-zA-Z]+(?=[ \t\r]*[\n#;])/ +naked_string = /[^\n]+?(?=[ \t\r]*\n)/ +*/ + +/*!lex2php +%statename START + +commentstart { + $this->token = Smarty_Internal_Configfileparser::TPC_COMMENTSTART; + $this->yypushstate(self::COMMENT); +} +openB { + $this->token = Smarty_Internal_Configfileparser::TPC_OPENB; + $this->yypushstate(self::SECTION); +} +closeB { + $this->token = Smarty_Internal_Configfileparser::TPC_CLOSEB; +} +equal { + $this->token = Smarty_Internal_Configfileparser::TPC_EQUAL; + $this->yypushstate(self::VALUE); +} +whitespace { + return false; +} +newline { + $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE; +} +id { + $this->token = Smarty_Internal_Configfileparser::TPC_ID; +} +text { + $this->token = Smarty_Internal_Configfileparser::TPC_OTHER; +} + +*/ + +/*!lex2php +%statename VALUE + +whitespace { + return false; +} +float { + $this->token = Smarty_Internal_Configfileparser::TPC_FLOAT; + $this->yypopstate(); +} +int { + $this->token = Smarty_Internal_Configfileparser::TPC_INT; + $this->yypopstate(); +} +tripple_quotes { + $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES; + $this->yypushstate(self::TRIPPLE); +} +single_quoted_string { + $this->token = Smarty_Internal_Configfileparser::TPC_SINGLE_QUOTED_STRING; + $this->yypopstate(); +} +double_quoted_string { + $this->token = Smarty_Internal_Configfileparser::TPC_DOUBLE_QUOTED_STRING; + $this->yypopstate(); +} +maybe_bool { + 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 + } else { + $this->token = Smarty_Internal_Configfileparser::TPC_BOOL; + $this->yypopstate(); + } +} +naked_string { + $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; + $this->yypopstate(); +} +newline { + $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; + $this->value = ""; + $this->yypopstate(); +} + +*/ + +/*!lex2php +%statename NAKED_STRING_VALUE + +naked_string { + $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; + $this->yypopstate(); +} + +*/ + +/*!lex2php +%statename COMMENT + +whitespace { + return false; +} +naked_string { + $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING; +} +newline { + $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE; + $this->yypopstate(); +} + +*/ + +/*!lex2php +%statename SECTION + +dot { + $this->token = Smarty_Internal_Configfileparser::TPC_DOT; +} +section { + $this->token = Smarty_Internal_Configfileparser::TPC_SECTION; + $this->yypopstate(); +} + +*/ +/*!lex2php +%statename TRIPPLE + +tripple_quotes_end { + $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES_END; + $this->yypopstate(); + $this->yypushstate(self::START); +} +text { + $to = strlen($this->data); + preg_match("/\"\"\"[ \t\r]*[\n#;]/",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } else { + $this->compiler->trigger_template_error ("missing or misspelled literal closing tag"); + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_TEXT; +} +*/ + +} diff --git a/library/Smarty/lexer/smarty_internal_configfileparser.y b/library/Smarty/lexer/smarty_internal_configfileparser.y new file mode 100644 index 000000000..ac961772d --- /dev/null +++ b/library/Smarty/lexer/smarty_internal_configfileparser.y @@ -0,0 +1,362 @@ +/** +* Smarty Internal Plugin Configfileparser +* +* This is the config file parser +* +* +* @package Smarty +* @subpackage Config +* @author Uwe Tews +*/ +%name TPC_ +%declare_class { +/** +* Smarty Internal Plugin Configfileparse +* +* This is the config file parser. +* It is generated from the smarty_internal_configfileparser.y file +* @package Smarty +* @subpackage Compiler +* @author Uwe Tews +*/ +class Smarty_Internal_Configfileparser +} +%include_class +{ + /** + * result status + * + * @var bool + */ + public $successful = true; + /** + * return value + * + * @var mixed + */ + public $retvalue = 0; + /** + * @var + */ + public $yymajor; + /** + * lexer object + * + * @var Smarty_Internal_Configfilelexer + */ + private $lex; + /** + * internal error flag + * + * @var bool + */ + private $internalError = false; + /** + * compiler object + * + * @var Smarty_Internal_Config_File_Compiler + */ + public $compiler = null; + /** + * smarty object + * + * @var Smarty + */ + public $smarty = null; + /** + * copy of config_overwrite property + * + * @var bool + */ + private $configOverwrite = false; + /** + * copy of config_read_hidden property + * + * @var bool + */ + private $configReadHidden = false; + /** + * helper map + * + * @var array + */ + private static $escapes_single = Array('\\' => '\\', + '\'' => '\''); + + /** + * constructor + * + * @param Smarty_Internal_Configfilelexer $lex + * @param Smarty_Internal_Config_File_Compiler $compiler + */ + function __construct(Smarty_Internal_Configfilelexer $lex, Smarty_Internal_Config_File_Compiler $compiler) + { + // set instance object + self::instance($this); + $this->lex = $lex; + $this->smarty = $compiler->smarty; + $this->compiler = $compiler; + $this->configOverwrite = $this->smarty->config_overwrite; + $this->configReadHidden = $this->smarty->config_read_hidden; + } + + /** + * @param null $new_instance + * + * @return null + */ + public static function &instance($new_instance = null) + { + static $instance = null; + if (isset($new_instance) && is_object($new_instance)) { + $instance = $new_instance; + } + return $instance; + } + + /** + * parse optional boolean keywords + * + * @param string $str + * + * @return bool + */ + private function parse_bool($str) + { + $str = strtolower($str); + if (in_array($str, array('on', 'yes', 'true'))) { + $res = true; + } else { + $res = false; + } + return $res; + } + + /** + * parse single quoted string + * remove outer quotes + * unescape inner quotes + * + * @param string $qstr + * + * @return string + */ + private static function parse_single_quoted_string($qstr) + { + $escaped_string = substr($qstr, 1, strlen($qstr) - 2); //remove outer quotes + + $ss = preg_split('/(\\\\.)/', $escaped_string, - 1, PREG_SPLIT_DELIM_CAPTURE); + + $str = ""; + foreach ($ss as $s) { + if (strlen($s) === 2 && $s[0] === '\\') { + if (isset(self::$escapes_single[$s[1]])) { + $s = self::$escapes_single[$s[1]]; + } + } + $str .= $s; + } + return $str; + } + + /** + * parse double quoted string + * + * @param string $qstr + * + * @return string + */ + private static function parse_double_quoted_string($qstr) + { + $inner_str = substr($qstr, 1, strlen($qstr) - 2); + return stripcslashes($inner_str); + } + + /** + * parse triple quoted string + * + * @param string $qstr + * + * @return string + */ + private static function parse_tripple_double_quoted_string($qstr) + { + return stripcslashes($qstr); + } + + /** + * set a config variable in target array + * + * @param array $var + * @param array $target_array + */ + private function set_var(Array $var, Array &$target_array) + { + $key = $var["key"]; + $value = $var["value"]; + + if ($this->configOverwrite || !isset($target_array['vars'][$key])) { + $target_array['vars'][$key] = $value; + } else { + settype($target_array['vars'][$key], 'array'); + $target_array['vars'][$key][] = $value; + } + } + + /** + * add config variable to global vars + * + * @param array $vars + */ + private function add_global_vars(Array $vars) + { + if (!isset($this->compiler->config_data['vars'])) { + $this->compiler->config_data['vars'] = Array(); + } + foreach ($vars as $var) { + $this->set_var($var, $this->compiler->config_data); + } + } + + /** + * add config variable to section + * + * @param string $section_name + * @param array $vars + */ + private function add_section_vars($section_name, Array $vars) + { + if (!isset($this->compiler->config_data['sections'][$section_name]['vars'])) { + $this->compiler->config_data['sections'][$section_name]['vars'] = Array(); + } + foreach ($vars as $var) { + $this->set_var($var, $this->compiler->config_data['sections'][$section_name]); + } + } +} + +%token_prefix TPC_ + +%parse_accept +{ + $this->successful = !$this->internalError; + $this->internalError = false; + $this->retvalue = $this->_retvalue; +} + +%syntax_error +{ + $this->internalError = true; + $this->yymajor = $yymajor; + $this->compiler->trigger_config_file_error(); +} + +%stack_overflow +{ + $this->internalError = true; + $this->compiler->trigger_config_file_error("Stack overflow in configfile parser"); +} + +// Complete config file +start(res) ::= global_vars sections. { + res = null; +} + +// Global vars +global_vars(res) ::= var_list(vl). { + $this->add_global_vars(vl); + res = null; +} + +// Sections +sections(res) ::= sections section. { + res = null; +} + +sections(res) ::= . { + res = null; +} + +section(res) ::= OPENB SECTION(i) CLOSEB newline var_list(vars). { + $this->add_section_vars(i, vars); + res = null; +} + +section(res) ::= OPENB DOT SECTION(i) CLOSEB newline var_list(vars). { + if ($this->configReadHidden) { + $this->add_section_vars(i, vars); + } + res = null; +} + +// Var list +var_list(res) ::= var_list(vl) newline. { + res = vl; +} + +var_list(res) ::= var_list(vl) var(v). { + res = array_merge(vl, Array(v)); +} + +var_list(res) ::= . { + res = Array(); +} + + +// Var +var(res) ::= ID(id) EQUAL value(v). { + res = Array("key" => id, "value" => v); +} + + +value(res) ::= FLOAT(i). { + res = (float) i; +} + +value(res) ::= INT(i). { + res = (int) i; +} + +value(res) ::= BOOL(i). { + res = $this->parse_bool(i); +} + +value(res) ::= SINGLE_QUOTED_STRING(i). { + res = self::parse_single_quoted_string(i); +} + +value(res) ::= DOUBLE_QUOTED_STRING(i). { + res = self::parse_double_quoted_string(i); +} + +value(res) ::= TRIPPLE_QUOTES(i) TRIPPLE_TEXT(c) TRIPPLE_QUOTES_END(ii). { + res = self::parse_tripple_double_quoted_string(c); +} + +value(res) ::= TRIPPLE_QUOTES(i) TRIPPLE_QUOTES_END(ii). { + res = ''; +} + +value(res) ::= NAKED_STRING(i). { + res = i; +} + +// NOTE: this is not a valid rule +// It is added hier to produce a usefull error message on a missing '='; +value(res) ::= OTHER(i). { + res = i; +} + + +// Newline and comments +newline(res) ::= NEWLINE. { + res = null; +} + +newline(res) ::= COMMENTSTART NEWLINE. { + res = null; +} + +newline(res) ::= COMMENTSTART NAKED_STRING NEWLINE. { + res = null; +} diff --git a/library/Smarty/lexer/smarty_internal_templatelexer.plex b/library/Smarty/lexer/smarty_internal_templatelexer.plex new file mode 100644 index 000000000..e36df5970 --- /dev/null +++ b/library/Smarty/lexer/smarty_internal_templatelexer.plex @@ -0,0 +1,770 @@ + 'TEXT', 2 => 'TAG', 3 => 'TAGBODY', 4 => 'LITERAL', 5 => 'DOUBLEQUOTEDSTRING', + 6 => 'CHILDBODY', 7 => 'CHILDBLOCK', 8 => 'CHILDLITERAL'); + + /** + * storage for assembled token patterns + * + * @var string + */ + 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; + + private $yy_global_pattern7 = null; + + private $yy_global_pattern8 = null; + + /** + * token names + * + * @var array + */ + public $smarty_token_names = array( // Text for parser error messages + 'NOT' => '(!,not)', + 'OPENP' => '(', + 'CLOSEP' => ')', + 'OPENB' => '[', + 'CLOSEB' => ']', + 'PTR' => '->', + 'APTR' => '=>', + 'EQUAL' => '=', + 'NUMBER' => 'number', + 'UNIMATH' => '+" , "-', + 'MATH' => '*" , "/" , "%', + 'INCDEC' => '++" , "--', + 'SPACE' => ' ', + 'DOLLAR' => '$', + 'SEMICOLON' => ';', + 'COLON' => ':', + 'DOUBLECOLON' => '::', + 'AT' => '@', + 'HATCH' => '#', + 'QUOTE' => '"', + 'BACKTICK' => '`', + 'VERT' => '"|" modifier', + 'DOT' => '.', + 'COMMA' => '","', + 'QMARK' => '"?"', + 'ID' => 'id, name', + 'TEXT' => 'text', + 'LDELSLASH' => '{/..} closing tag', + 'LDEL' => '{...} Smarty tag', + 'COMMENT' => 'comment', + 'AS' => 'as', + 'TO' => 'to', + 'PHP' => '" '"<", "==" ... logical operator', + 'TLOGOP' => '"lt", "eq" ... logical operator; "is div by" ... if condition', + 'SCOND' => '"is even" ... if condition', + ); + + /** + * constructor + * + * @param string $data template source + * @param Smarty_Internal_TemplateCompilerBase $compiler + */ + function __construct($data, Smarty_Internal_TemplateCompilerBase $compiler) + { + $this->data = $data; + $this->counter = 0; + if (preg_match('~^\xEF\xBB\xBF~i', $this->data, $match)) { + $this->counter += strlen($match[0]); + } + $this->line = 1; + $this->smarty = $compiler->smarty; + $this->compiler = $compiler; + $this->ldel = preg_quote($this->smarty->left_delimiter, '~'); + $this->ldel_length = strlen($this->smarty->left_delimiter); + $this->rdel = preg_quote($this->smarty->right_delimiter, '~'); + $this->rdel_length = strlen($this->smarty->right_delimiter); + $this->smarty_token_names['LDEL'] = $this->smarty->left_delimiter; + $this->smarty_token_names['RDEL'] = $this->smarty->right_delimiter; + } + + public function PrintTrace() + { + $this->yyTraceFILE = fopen('php://output', 'w'); + $this->yyTracePrompt = '
'; + } + + /* + * Check if this tag is autoliteral + */ + public function isAutoLiteral () + { + return $this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false; + } + + /*!lex2php + %input $this->data + %counter $this->counter + %token $this->token + %value $this->value + %line $this->line + linebreak = ~[\t ]*[\r\n]+[\t ]*~ + text = ~[\S\s]~ + textdoublequoted = ~([^"\\]*?)((?:\\.[^"\\]*?)*?)(?=(SMARTYldel|\$|`\$|"))~ + namespace = ~([0-9]*[a-zA-Z_]\w*)?(\\[0-9]*[a-zA-Z_]\w*)+~ + all = ~[\S\s]+~ + emptyjava = ~[{][}]~ + phpstart = ~(<[?]((php\s+|=)|\s+))|(<[%])|(<[?]xml\s+)|()|([?][>])|([%][>])|(SMARTYldel\s*php(.*?)SMARTYrdel)|(SMARTYldel\s*[/]phpSMARTYrdel)~ + slash = ~[/]~ + ldel = ~SMARTYldel\s*~ + rdel = ~\s*SMARTYrdel~ + nocacherdel = ~(\s+nocache)?\s*SMARTYrdel~ + notblockid = ~(?:(?!block)[0-9]*[a-zA-Z_]\w*)~ + smartyblockchildparent = ~[\$]smarty\.block\.(child|parent)~ + integer = ~\d+~ + hex = ~0[xX][0-9a-fA-F]+~ + math = ~\s*([*]{1,2}|[%/^&]|[<>]{2})\s*~ + comment = ~SMARTYldel[*]~ + incdec = ~([+]|[-]){2}~ + unimath = ~\s*([+]|[-])\s*~ + openP = ~\s*[(]\s*~ + closeP = ~\s*[)]~ + openB = ~\[\s*~ + closeB = ~\s*\]~ + dollar = ~[$]~ + dot = ~[.]~ + comma = ~\s*[,]\s*~ + doublecolon = ~[:]{2}~ + colon = ~\s*[:]\s*~ + at = ~[@]~ + hatch = ~[#]~ + semicolon = ~\s*[;]\s*~ + equal = ~\s*[=]\s*~ + space = ~\s+~ + ptr = ~\s*[-][>]\s*~ + aptr = ~\s*[=][>]\s*~ + singlequotestring = ~'[^'\\]*(?:\\.[^'\\]*)*'~ + backtick = ~[`]~ + vert = ~[|]~ + qmark = ~\s*[?]\s*~ + constant = ~([_]+[A-Z0-9][0-9A-Z_]*|[A-Z][0-9A-Z_]*)(?![0-9A-Z_]*[a-z])~ + attr = ~\s+[0-9]*[a-zA-Z_][a-zA-Z0-9_\-:]*\s*[=]\s*~ + id = ~[0-9]*[a-zA-Z_]\w*~ + literal = ~literal~ + strip = ~strip~ + lop = ~\s*(([!=][=]{1,2})|([<][=>]?)|([>][=]?)|[&|]{2})\s*~ + tlop = ~\s+(eq|ne|neq|gt|ge|gte|lt|le|lte|mod|and|or|xor|(is\s+(not\s+)?(odd|even|div)\s+by))\s+~ + scond = ~\s+is\s+(not\s+)?(odd|even)~ + isin = ~\s+is\s+in\s+~ + as = ~\s+as\s+~ + to = ~\s+to\s+~ + step = ~\s+step\s+~ + block = ~block~ + if = ~(if|elseif|else if|while)\s+~ + for = ~for\s+~ + foreach = ~foreach(?![^\s])~ + setfilter = ~setfilter\s+~ + instanceof = ~\s+instanceof\s+~ + not = ~([!]\s*)|(not\s+)~ + typecast = ~[(](int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)[)]\s*~ + double_quote = ~["]~ + single_quote = ~[']~ + */ + /*!lex2php + %statename TEXT + emptyjava { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + comment { + preg_match("~[*]{$this->rdel}~",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1] + strlen($match[0][0]); + } else { + $this->compiler->trigger_template_error ("missing or misspelled comment closing tag '*{$this->smarty->right_delimiter}'"); + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + return false; + } + phpstart { + $obj = new Smarty_Internal_Compile_Private_Php(); + $obj->parsePhp($this); + } + ldel literal rdel { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } else { + $this->token = Smarty_Internal_Templateparser::TP_LITERALSTART; + $this->yypushstate(self::LITERAL); + } + } + ldel { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } else { + $this->yypushstate(self::TAG); + return true; + } + } + rdel { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + text { + $to = strlen($this->data); + preg_match("~($this->ldel)|([<]script\s+language\s*=\s*[\"\']?\s*php\s*[\"\']?\s*[>])|([<][?])|([<][%])|([?][>])|([%][>])~i",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + */ + /*!lex2php + %statename TAG + ldel if { + $this->token = Smarty_Internal_Templateparser::TP_LDELIF; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + ldel for { + $this->token = Smarty_Internal_Templateparser::TP_LDELFOR; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + ldel foreach { + $this->token = Smarty_Internal_Templateparser::TP_LDELFOREACH; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + ldel setfilter { + $this->token = Smarty_Internal_Templateparser::TP_LDELSETFILTER; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + ldel id nocacherdel { + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_SIMPLETAG; + $this->taglineno = $this->line; + } + ldel slash notblockid rdel { + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_CLOSETAG; + $this->taglineno = $this->line; + } + ldel dollar id nocacherdel { + if ($this->_yy_stack[count($this->_yy_stack)-1] == self::TEXT) { + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_SIMPLEOUTPUT; + $this->taglineno = $this->line; + } else { + $this->value = $this->smarty->left_delimiter; + $this->token = Smarty_Internal_Templateparser::TP_LDEL; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + } + ldel slash { + $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + ldel { + $this->token = Smarty_Internal_Templateparser::TP_LDEL; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + */ + /*!lex2php + %statename TAGBODY + rdel { + $this->token = Smarty_Internal_Templateparser::TP_RDEL; + $this->yypopstate(); + } + double_quote { + $this->token = Smarty_Internal_Templateparser::TP_QUOTE; + $this->yypushstate(self::DOUBLEQUOTEDSTRING); + } + singlequotestring { + $this->token = Smarty_Internal_Templateparser::TP_SINGLEQUOTESTRING; + } + smartyblockchildparent { + $this->token = Smarty_Internal_Templateparser::TP_SMARTYBLOCKCHILDPARENT; + $this->taglineno = $this->line; + } + dollar id { + $this->token = Smarty_Internal_Templateparser::TP_DOLLARID; + } + dollar { + $this->token = Smarty_Internal_Templateparser::TP_DOLLAR; + } + isin { + $this->token = Smarty_Internal_Templateparser::TP_ISIN; + } + as { + $this->token = Smarty_Internal_Templateparser::TP_AS; + } + to { + $this->token = Smarty_Internal_Templateparser::TP_TO; + } + step { + $this->token = Smarty_Internal_Templateparser::TP_STEP; + } + instanceof { + $this->token = Smarty_Internal_Templateparser::TP_INSTANCEOF; + } + lop { + $this->token = Smarty_Internal_Templateparser::TP_LOGOP; + } + tlop { + $this->token = Smarty_Internal_Templateparser::TP_TLOGOP; + } + scond { + $this->token = Smarty_Internal_Templateparser::TP_SINGLECOND; + } + not{ + $this->token = Smarty_Internal_Templateparser::TP_NOT; + } + typecast { + $this->token = Smarty_Internal_Templateparser::TP_TYPECAST; + } + openP { + $this->token = Smarty_Internal_Templateparser::TP_OPENP; + } + closeP { + $this->token = Smarty_Internal_Templateparser::TP_CLOSEP; + } + openB { + $this->token = Smarty_Internal_Templateparser::TP_OPENB; + } + closeB { + $this->token = Smarty_Internal_Templateparser::TP_CLOSEB; + } + ptr { + $this->token = Smarty_Internal_Templateparser::TP_PTR; + } + aptr { + $this->token = Smarty_Internal_Templateparser::TP_APTR; + } + equal { + $this->token = Smarty_Internal_Templateparser::TP_EQUAL; + } + incdec { + $this->token = Smarty_Internal_Templateparser::TP_INCDEC; + } + unimath { + $this->token = Smarty_Internal_Templateparser::TP_UNIMATH; + } + math { + $this->token = Smarty_Internal_Templateparser::TP_MATH; + } + at { + $this->token = Smarty_Internal_Templateparser::TP_AT; + } + hatch { + $this->token = Smarty_Internal_Templateparser::TP_HATCH; + } + attr { + // resolve conflicts with shorttag and right_delimiter starting with '=' + if (substr($this->data, $this->counter + strlen($this->value) - 1, $this->rdel_length) == $this->smarty->right_delimiter) { + preg_match("~\s+~",$this->value,$match); + $this->value = $match[0]; + $this->token = Smarty_Internal_Templateparser::TP_SPACE; + } else { + $this->token = Smarty_Internal_Templateparser::TP_ATTR; + } + } + namespace { + $this->token = Smarty_Internal_Templateparser::TP_NAMESPACE; + } + id { + $this->token = Smarty_Internal_Templateparser::TP_ID; + } + integer { + $this->token = Smarty_Internal_Templateparser::TP_INTEGER; + } + backtick { + $this->token = Smarty_Internal_Templateparser::TP_BACKTICK; + $this->yypopstate(); + } + vert { + $this->token = Smarty_Internal_Templateparser::TP_VERT; + } + dot { + $this->token = Smarty_Internal_Templateparser::TP_DOT; + } + comma { + $this->token = Smarty_Internal_Templateparser::TP_COMMA; + } + semicolon { + $this->token = Smarty_Internal_Templateparser::TP_SEMICOLON; + } + doublecolon { + $this->token = Smarty_Internal_Templateparser::TP_DOUBLECOLON; + } + colon { + $this->token = Smarty_Internal_Templateparser::TP_COLON; + } + qmark { + $this->token = Smarty_Internal_Templateparser::TP_QMARK; + } + hex { + $this->token = Smarty_Internal_Templateparser::TP_HEX; + } + space { + $this->token = Smarty_Internal_Templateparser::TP_SPACE; + } + ldel { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } else { + $this->yypushstate(self::TAG); + return true; + } + } + text { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + */ + + /*!lex2php + %statename LITERAL + ldel literal rdel { + $this->literal_cnt++; + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; + } + ldel slash literal rdel { + if ($this->literal_cnt) { + $this->literal_cnt--; + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; + } else { + $this->token = Smarty_Internal_Templateparser::TP_LITERALEND; + $this->yypopstate(); + } + } + text { + $to = strlen($this->data); + preg_match("~{$this->ldel}[/]?literal{$this->rdel}~i",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } else { + $this->compiler->trigger_template_error ("missing or misspelled literal closing tag"); + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; + } + */ + /*!lex2php + %statename DOUBLEQUOTEDSTRING + ldel literal rdel { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + ldel slash literal rdel { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + ldel slash { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } else { + $this->yypushstate(self::TAG); + return true; + } + } + ldel id { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } else { + $this->yypushstate(self::TAG); + return true; + } + } + ldel { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } else { + $this->token = Smarty_Internal_Templateparser::TP_LDEL; + $this->taglineno = $this->line; + $this->yypushstate(self::TAGBODY); + } + } + double_quote { + $this->token = Smarty_Internal_Templateparser::TP_QUOTE; + $this->yypopstate(); + } + backtick dollar { + $this->token = Smarty_Internal_Templateparser::TP_BACKTICK; + $this->value = substr($this->value,0,-1); + $this->yypushstate(self::TAGBODY); + $this->taglineno = $this->line; + } + dollar id { + $this->token = Smarty_Internal_Templateparser::TP_DOLLARID; + } + dollar { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + textdoublequoted { + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + text { + $to = strlen($this->data); + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + */ + /*!lex2php + %statename CHILDBODY + ldel strip rdel { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + return false; + } else { + $this->token = Smarty_Internal_Templateparser::TP_STRIPON; + } + } + ldel slash strip rdel { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + return false; + } else { + $this->token = Smarty_Internal_Templateparser::TP_STRIPOFF; + } + } + ldel block { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + return false; + } else { + $this->yypopstate(); + return true; + } + } + text { + $to = strlen($this->data); + preg_match("~SMARTYldel\s*(([/])?strip\s*SMARTYrdel|block\s+)~i",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + return false; + } + + */ + /*!lex2php + %statename CHILDBLOCK + ldel literal rdel { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + $this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE; + } else { + $this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE; + $this->yypushstate(self::CHILDLITERAL); + } + } + ldel block { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + $this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE; + } else { + $this->yypopstate(); + return true; + } + } + ldel slash block { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + $this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE; + } else { + $this->yypopstate(); + return true; + } + } + ldel smartyblockchildparent { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + $this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE; + } else { + $this->yypopstate(); + return true; + } + } + text { + $to = strlen($this->data); + preg_match("~SMARTYldel\s*(literal\s*SMARTYrdel|([/])?block(\s|SMARTYrdel)|[\$]smarty\.block\.(child|parent))~i",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE; + } + */ + /*!lex2php + %statename CHILDLITERAL + ldel literal rdel { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + $this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE; + } else { + $this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE; + $this->yypushstate(self::CHILDLITERAL); + } + } + ldel slash literal rdel { + if ($this->smarty->auto_literal && isset($this->value[$this->ldel_length]) ? strpos(" \n\t\r", $this->value[$this->ldel_length]) !== false : false) { + $this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE; + } else { + $this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE; + $this->yypopstate(); + } + } + text { + $to = strlen($this->data); + preg_match("~{$this->ldel}[/]?literal\s*{$this->rdel}~i",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } else { + $this->compiler->trigger_template_error ("missing or misspelled literal closing tag"); + } + $this->value = substr($this->data,$this->counter,$to-$this->counter); + $this->token = Smarty_Internal_Templateparser::TP_BLOCKSOURCE; + } + */ + } + + \ No newline at end of file diff --git a/library/Smarty/lexer/smarty_internal_templateparser.y b/library/Smarty/lexer/smarty_internal_templateparser.y new file mode 100644 index 000000000..225f71b24 --- /dev/null +++ b/library/Smarty/lexer/smarty_internal_templateparser.y @@ -0,0 +1,1329 @@ +/** +* Smarty Internal Plugin Templateparser +* +* This is the template parser +* +* +* @package Smarty +* @subpackage Compiler +* @author Uwe Tews +*/ +%stack_size 500 +%name TP_ +%declare_class { +/** +* Smarty Internal Plugin Templateparser +* +* This is the template parser. +* It is generated from the smarty_internal_templateparser.y file +* @package Smarty +* @subpackage Compiler +* @author Uwe Tews +*/ +class Smarty_Internal_Templateparser +} +%include_class +{ + const Err1 = "Security error: Call to private object member not allowed"; + const Err2 = "Security error: Call to dynamic object member not allowed"; + const Err3 = "PHP in template not allowed. Use SmartyBC to enable it"; + + /** + * result status + * + * @var bool + */ + public $successful = true; + /** + * return value + * + * @var mixed + */ + public $retvalue = 0; + /** + * counter for prefix code + * + * @var int + */ + public static $prefix_number = 0; + /** + * @var + */ + public $yymajor; + /** + * last index of array variable + * + * @var mixed + */ + public $last_index; + /** + * last variable name + * + * @var string + */ + public $last_variable; + /** + * root parse tree buffer + * + * @var Smarty_Internal_ParseTree + */ + public $root_buffer; + /** + * current parse tree object + * + * @var Smarty_Internal_ParseTree + */ + public $current_buffer; + /** + * lexer object + * + * @var Smarty_Internal_Templatelexer + */ + private $lex; + /** + * internal error flag + * + * @var bool + */ + private $internalError = false; + /** + * {strip} status + * + * @var bool + */ + public $strip = false; + /** + * compiler object + * + * @var Smarty_Internal_TemplateCompilerBase + */ + public $compiler = null; + /** + * smarty object + * + * @var Smarty + */ + public $smarty = null; + /** + * template object + * + * @var Smarty_Internal_Template + */ + public $template = null; + /** + * block nesting level + * + * @var int + */ + public $block_nesting_level = 0; + + /** + * security object + * + * @var Smarty_Security + */ + private $security = null; + + /** + * constructor + * + * @param Smarty_Internal_Templatelexer $lex + * @param Smarty_Internal_TemplateCompilerBase $compiler + */ + function __construct(Smarty_Internal_Templatelexer $lex, Smarty_Internal_TemplateCompilerBase $compiler) + { + $this->lex = $lex; + $this->compiler = $compiler; + $this->template = $this->compiler->template; + $this->smarty = $this->template->smarty; + $this->security = isset($this->smarty->security_policy) ? $this->smarty->security_policy : false; + $this->current_buffer = $this->root_buffer = new Smarty_Internal_ParseTree_Template($this); + } + + /** + * insert PHP code in current buffer + * + * @param string $code + */ + public function insertPhpCode($code) + { + $this->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($this, $code)); + } + + /** + * merge PHP code with prefix code and return parse tree tag object + * + * @param string $code + * + * @return Smarty_Internal_ParseTree_Tag + */ + public function mergePrefixCode($code) + { + $tmp =''; + foreach ($this->compiler->prefix_code as $preCode) { + $tmp = empty($tmp) ? $preCode : $this->compiler->appendCode($tmp, $preCode); + } + $this->compiler->prefix_code=array(); + $tmp = empty($tmp) ? $code : $this->compiler->appendCode($tmp, $code); + return new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode($tmp,true)); + } + +} + +%token_prefix TP_ + +%parse_accept +{ + $this->successful = !$this->internalError; + $this->internalError = false; + $this->retvalue = $this->_retvalue; +} + +%syntax_error +{ + $this->internalError = true; + $this->yymajor = $yymajor; + $this->compiler->trigger_template_error(); +} + +%stack_overflow +{ + $this->internalError = true; + $this->compiler->trigger_template_error("Stack overflow in template parser"); +} + +%left VERT. +%left COLON. + + // + // complete template + // +start(res) ::= template. { + res = $this->root_buffer->to_smarty_php(); +} + + // + // loop over template elements + // + // single template element +template ::= template_element(e). { + if (e != null) { + $this->current_buffer->append_subtree(e); + } +} + + // loop of elements +template ::= template template_element(e). { + if (e != null) { + // because of possible code injection + $this->current_buffer->append_subtree(e); + } +} + + // empty template +template ::= . + +// +// template elements +// + // Smarty tag +template_element(res)::= smartytag(st). { + if ($this->compiler->has_code) { + res = $this->mergePrefixCode(st); + } else { + res = null; + } + $this->compiler->has_variable_string = false; + $this->block_nesting_level = count($this->compiler->_tag_stack); +} + + // Literal +template_element(res) ::= literal(l). { + res = new Smarty_Internal_ParseTree_Text($this, l); +} + // php tags +template_element(res)::= PHP(o). { + $code = $this->compiler->compileTag('private_php',array(array('code' => o), array('type' => $this->lex->phpType )),array()); + if ($this->compiler->has_code && !empty($code)) { + $tmp =''; foreach ($this->compiler->prefix_code as $code) {$tmp.=$code;} $this->compiler->prefix_code=array(); + res = new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode($tmp.$code,true)); + } else { + res = null; + } +} + + // nocache code +template_element(res)::= NOCACHE(c). { + $this->compiler->tag_nocache = true; + $save = $this->template->has_nocache_code; + res = new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode("\n", $this->compiler, true)); + $this->template->has_nocache_code = $save; +} + // template text +template_element(res)::= text_content(t). { + res = $this->compiler->processText(t); +} + +text_content(res) ::= TEXT(o). { + res = o; +} + +text_content(res) ::= text_content(t) TEXT(o). { + res = t . o; +} + + // strip on +template_element ::= STRIPON(d). { + $this->strip = true; +} + // strip off +template_element ::= STRIPOFF(d). { + $this->strip = false; +} + // process source of inheritance child block +template_element ::= BLOCKSOURCE(s). { + if ($this->strip) { + SMARTY_INTERNAL_COMPILE_BLOCK::blockSource($this->compiler, preg_replace('![\t ]*[\r\n]+[\t ]*!', '', s)); + } else { + SMARTY_INTERNAL_COMPILE_BLOCK::blockSource($this->compiler, s); + } +} + + // Litteral +literal(res) ::= LITERALSTART LITERALEND. { + res = ''; +} + +literal(res) ::= LITERALSTART literal_elements(l) LITERALEND. { + res = l; +} + +literal_elements(res) ::= literal_elements(l1) literal_element(l2). { + res = l1.l2; +} + +literal_elements(res) ::= . { + res = ''; +} + +literal_element(res) ::= literal(l). { + res = l; +} + +literal_element(res) ::= LITERAL(l). { + res = l; +} + +smartytag(res) ::= tag(t) RDEL. { + res = t; +} +// +// output tags start here +// +smartytag(res) ::= SIMPLEOUTPUT(i). { + $var = trim(substr(i, $this->lex->ldel_length, -$this->lex->rdel_length), ' $'); + if (preg_match('/^(.*)(\s+nocache)$/', $var, $match)) { + res = $this->compiler->compileTag('private_print_expression',array('nocache'),array('value'=>$this->compiler->compileVariable('\''.$match[1].'\''))); + } else { + res = $this->compiler->compileTag('private_print_expression',array(),array('value'=>$this->compiler->compileVariable('\''.$var.'\''))); + } +} + + // output with optional attributes +tag(res) ::= LDEL variable(e). { + res = $this->compiler->compileTag('private_print_expression',array(),array('value'=>e)); +} + +tag(res) ::= LDEL variable(e) attributes(a). { + res = $this->compiler->compileTag('private_print_expression',a,array('value'=>e)); +} +tag(res) ::= LDEL value(e). { + res = $this->compiler->compileTag('private_print_expression',array(),array('value'=>e)); +} +tag(res) ::= LDEL value(e) attributes(a). { + res = $this->compiler->compileTag('private_print_expression',a,array('value'=>e)); +} + +tag(res) ::= LDEL expr(e). { + res = $this->compiler->compileTag('private_print_expression',array(),array('value'=>e)); +} + +tag(res) ::= LDEL expr(e) attributes(a). { + res = $this->compiler->compileTag('private_print_expression',a,array('value'=>e)); +} + +// +// Smarty tags start here +// + + // assign new style +tag(res) ::= LDEL DOLLARID(i) EQUAL value(e). { + res = $this->compiler->compileTag('assign',array(array('value'=>e),array('var'=>'\''.substr(i,1).'\''))); +} + +tag(res) ::= LDEL DOLLARID(i) EQUAL expr(e). { + res = $this->compiler->compileTag('assign',array(array('value'=>e),array('var'=>'\''.substr(i,1).'\''))); +} + +tag(res) ::= LDEL DOLLARID(i) EQUAL expr(e) attributes(a). { + res = $this->compiler->compileTag('assign',array_merge(array(array('value'=>e),array('var'=>'\''.substr(i,1).'\'')),a)); +} + +tag(res) ::= LDEL varindexed(vi) EQUAL expr(e) attributes(a). { + res = $this->compiler->compileTag('assign',array_merge(array(array('value'=>e),array('var'=>vi['var'])),a),array('smarty_internal_index'=>vi['smarty_internal_index'])); +} + +// simple tag like {name} +smartytag(res)::= SIMPLETAG(t). { + $tag = trim(substr(t, $this->lex->ldel_length, -$this->lex->rdel_length)); + if ($tag == 'strip') { + $this->strip = true; + res = null;; + } else { + if (defined($tag)) { + if ($this->security) { + $this->security->isTrustedConstant($tag, $this->compiler); + } + res = $this->compiler->compileTag('private_print_expression',array(),array('value'=>$tag)); + } else { + if (preg_match('/^(.*)(\s+nocache)$/', $tag, $match)) { + res = $this->compiler->compileTag($match[1],array("'nocache'")); + } else { + res = $this->compiler->compileTag($tag,array()); + } + } + } +} + + // tag with optional Smarty2 style attributes +tag(res) ::= LDEL ID(i) attributes(a). { + if (defined(i)) { + if ($this->security) { + $this->security->isTrustedConstant(i, $this->compiler); + } + res = $this->compiler->compileTag('private_print_expression',a,array('value'=>i)); + } else { + res = $this->compiler->compileTag(i,a); + } +} +tag(res) ::= LDEL ID(i). { + if (defined(i)) { + if ($this->security) { + $this->security->isTrustedConstant(i, $this->compiler); + } + res = $this->compiler->compileTag('private_print_expression',array(),array('value'=>i)); + } else { + res = $this->compiler->compileTag(i,array()); + } +} + + + // tag with modifier and optional Smarty2 style attributes +tag(res) ::= LDEL ID(i) modifierlist(l)attributes(a). { + if (defined(i)) { + if ($this->security) { + $this->security->isTrustedConstant(i, $this->compiler); + } + res = $this->compiler->compileTag('private_print_expression',a,array('value'=>i, 'modifierlist'=>l)); + } else { + res = ''.$this->compiler->compileTag(i,a).'compiler->compileTag('private_modifier',array(),array('modifierlist'=>l,'value'=>'ob_get_clean()')).';?>'; + } +} + + // registered object tag +tag(res) ::= LDEL ID(i) PTR ID(m) attributes(a). { + res = $this->compiler->compileTag(i,a,array('object_method'=>m)); +} + + // registered object tag with modifiers +tag(res) ::= LDEL ID(i) PTR ID(me) modifierlist(l) attributes(a). { + res = ''.$this->compiler->compileTag(i,a,array('object_method'=>me)).'compiler->compileTag('private_modifier',array(),array('modifierlist'=>l,'value'=>'ob_get_clean()')).';?>'; +} + + // {if}, {elseif} and {while} tag +tag(res) ::= LDELIF(i) expr(ie). { + $tag = trim(substr(i,$this->lex->ldel_length)); + res = $this->compiler->compileTag(($tag == 'else if')? 'elseif' : $tag,array(),array('if condition'=>ie)); +} + +tag(res) ::= LDELIF(i) expr(ie) attributes(a). { + $tag = trim(substr(i,$this->lex->ldel_length)); + res = $this->compiler->compileTag(($tag == 'else if')? 'elseif' : $tag,a,array('if condition'=>ie)); +} + +tag(res) ::= LDELIF(i) statement(ie). { + $tag = trim(substr(i,$this->lex->ldel_length)); + res = $this->compiler->compileTag(($tag == 'else if')? 'elseif' : $tag,array(),array('if condition'=>ie)); +} + +tag(res) ::= LDELIF(i) statement(ie) attributes(a). { + $tag = trim(substr(i,$this->lex->ldel_length)); + res = $this->compiler->compileTag(($tag == 'else if')? 'elseif' : $tag,a,array('if condition'=>ie)); +} + + // {for} tag +tag(res) ::= LDELFOR statements(st) SEMICOLON expr(ie) SEMICOLON varindexed(v2) foraction(e2) attributes(a). { + res = $this->compiler->compileTag('for',array_merge(a,array(array('start'=>st),array('ifexp'=>ie),array('var'=>v2),array('step'=>e2))),1); +} + + foraction(res) ::= EQUAL expr(e). { + res = '='.e; +} + + foraction(res) ::= INCDEC(e). { + res = e; +} + +tag(res) ::= LDELFOR statement(st) TO expr(v) attributes(a). { + res = $this->compiler->compileTag('for',array_merge(a,array(array('start'=>st),array('to'=>v))),0); +} + +tag(res) ::= LDELFOR statement(st) TO expr(v) STEP expr(v2) attributes(a). { + res = $this->compiler->compileTag('for',array_merge(a,array(array('start'=>st),array('to'=>v),array('step'=>v2))),0); +} + + // {foreach} tag +tag(res) ::= LDELFOREACH attributes(a). { + res = $this->compiler->compileTag('foreach',a); +} + + // {foreach $array as $var} tag +tag(res) ::= LDELFOREACH SPACE value(v1) AS varvar(v0) attributes(a). { + res = $this->compiler->compileTag('foreach',array_merge(a,array(array('from'=>v1),array('item'=>v0)))); +} + +tag(res) ::= LDELFOREACH SPACE value(v1) AS varvar(v2) APTR varvar(v0) attributes(a). { + res = $this->compiler->compileTag('foreach',array_merge(a,array(array('from'=>v1),array('item'=>v0),array('key'=>v2)))); +} + +tag(res) ::= LDELFOREACH SPACE expr(e) AS varvar(v0) attributes(a). { + res = $this->compiler->compileTag('foreach',array_merge(a,array(array('from'=>e),array('item'=>v0)))); +} + +tag(res) ::= LDELFOREACH SPACE expr(e) AS varvar(v1) APTR varvar(v0) attributes(a). { + res = $this->compiler->compileTag('foreach',array_merge(a,array(array('from'=>e),array('item'=>v0),array('key'=>v1)))); +} + + // {setfilter} +tag(res) ::= LDELSETFILTER ID(m) modparameters(p). { + res = $this->compiler->compileTag('setfilter',array(),array('modifier_list'=>array(array_merge(array(m),p)))); +} + +tag(res) ::= LDELSETFILTER ID(m) modparameters(p) modifierlist(l). { + res = $this->compiler->compileTag('setfilter',array(),array('modifier_list'=>array_merge(array(array_merge(array(m),p)),l))); +} + + // {$smarty.block.child} or {$smarty.block.parent} +tag(res) ::= LDEL SMARTYBLOCKCHILDPARENT(i). { + $j = strrpos(i,'.'); + if (i[$j+1] == 'c') { + // {$smarty.block.child} + res = SMARTY_INTERNAL_COMPILE_BLOCK::compileChildBlock($this->compiler); + } else { + // {$smarty.block.parent} + res = SMARTY_INTERNAL_COMPILE_BLOCK::compileParentBlock($this->compiler); + } +} + + + // end of block tag {/....} +smartytag(res)::= CLOSETAG(t). { + $tag = trim(substr(t, $this->lex->ldel_length, -$this->lex->rdel_length), ' /'); + if ($tag == 'strip') { + $this->strip = false; + res = null; + } else { + res = $this->compiler->compileTag($tag.'close',array()); + } + } +tag(res) ::= LDELSLASH ID(i). { + res = $this->compiler->compileTag(i.'close',array()); +} + +tag(res) ::= LDELSLASH ID(i) modifierlist(l). { + res = $this->compiler->compileTag(i.'close',array(),array('modifier_list'=>l)); +} + + // end of block object tag {/....} +tag(res) ::= LDELSLASH ID(i) PTR ID(m). { + res = $this->compiler->compileTag(i.'close',array(),array('object_method'=>m)); +} + +tag(res) ::= LDELSLASH ID(i) PTR ID(m) modifierlist(l). { + res = $this->compiler->compileTag(i.'close',array(),array('object_method'=>m, 'modifier_list'=>l)); +} + +// +//Attributes of Smarty tags +// + // list of attributes +attributes(res) ::= attributes(a1) attribute(a2). { + res = a1; + res[] = a2; +} + + // single attribute +attributes(res) ::= attribute(a). { + res = array(a); +} + + // no attributes +attributes(res) ::= . { + res = array(); +} + + // attribute +attribute(res) ::= SPACE ID(v) EQUAL ID(id). { + if (defined(id)) { + if ($this->security) { + $this->security->isTrustedConstant(id, $this->compiler); + } + res = array(v=>id); + } else { + res = array(v=>'\''.id.'\''); + } +} + +attribute(res) ::= ATTR(v) expr(e). { + res = array(trim(v," =\n\r\t")=>e); +} + +attribute(res) ::= ATTR(v) value(e). { + res = array(trim(v," =\n\r\t")=>e); +} + +attribute(res) ::= SPACE ID(v). { + res = '\''.v.'\''; +} + +attribute(res) ::= SPACE expr(e). { + res = e; +} + +attribute(res) ::= SPACE value(v). { + res = v; +} + +attribute(res) ::= SPACE INTEGER(i) EQUAL expr(e). { + res = array(i=>e); +} + + + +// +// statement +// +statements(res) ::= statement(s). { + res = array(s); +} + +statements(res) ::= statements(s1) COMMA statement(s). { + s1[]=s; + res = s1; +} + +statement(res) ::= DOLLARID(i) EQUAL INTEGER(e). { + res = array('var' => '\''.substr(i,1).'\'', 'value'=>e); +} +statement(res) ::= DOLLARID(i) EQUAL expr(e). { + res = array('var' => '\''.substr(i,1).'\'', 'value'=>e); +} + +statement(res) ::= varindexed(vi) EQUAL expr(e). { + res = array('var' => vi, 'value'=>e); +} + +statement(res) ::= OPENP statement(st) CLOSEP. { + res = st; +} + + +// +// expressions +// + + // single value +expr(res) ::= value(v). { + res = v; +} + + // ternary +expr(res) ::= ternary(v). { + res = v; +} + + // resources/streams +expr(res) ::= DOLLARID(i) COLON ID(i2). { + res = '$_smarty_tpl->getStreamVariable(\''.substr(i,1).'://' . i2 . '\')'; +} + + // arithmetic expression +expr(res) ::= expr(e) MATH(m) value(v). { + res = e . trim(m) . v; +} + +expr(res) ::= expr(e) UNIMATH(m) value(v). { + res = e . trim(m) . v; +} + + // array +expr(res) ::= array(a). { + res = a; +} + + // modifier +expr(res) ::= expr(e) modifierlist(l). { + res = $this->compiler->compileTag('private_modifier',array(),array('value'=>e,'modifierlist'=>l)); +} + +// if expression + // simple expression +expr(res) ::= expr(e1) lop(c) expr(e2). { + res = (isset(c['pre']) ? c['pre'] : '') . e1.c['op'].e2 . (isset(c['pre']) ? ')' : ''); +} +expr(res) ::= expr(e1) scond(c). { + res = c . e1 . ')'; +} + +expr(res) ::= expr(e1) ISIN array(a). { + res = 'in_array('.e1.','.a.')'; +} + +expr(res) ::= expr(e1) ISIN value(v). { + res = 'in_array('.e1.',(array)'.v.')'; +} + +expr(res) ::= variable(v1) INSTANCEOF(i) ns1(v2). { + res = v1.i.v2; +} + + +// +// ternary +// +ternary(res) ::= OPENP expr(v) CLOSEP QMARK DOLLARID(e1) COLON expr(e2). { + res = v.' ? '. $this->compiler->compileVariable('\''.substr(e1,1).'\'') . ' : '.e2; +} + +ternary(res) ::= OPENP expr(v) CLOSEP QMARK expr(e1) COLON expr(e2). { + res = v.' ? '.e1.' : '.e2; +} + + // value +value(res) ::= variable(v). { + res = v; +} + + // +/- value +value(res) ::= UNIMATH(m) value(v). { + res = m.v; +} + + // logical negation +value(res) ::= NOT value(v). { + res = '!'.v; +} + +value(res) ::= TYPECAST(t) value(v). { + res = t.v; +} + +value(res) ::= variable(v) INCDEC(o). { + res = v.o; +} + + // numeric +value(res) ::= HEX(n). { + res = n; +} + +value(res) ::= INTEGER(n). { + res = n; +} + +value(res) ::= INTEGER(n1) DOT INTEGER(n2). { + res = n1.'.'.n2; +} + +value(res) ::= INTEGER(n1) DOT. { + res = n1.'.'; +} + +value(res) ::= DOT INTEGER(n1). { + res = '.'.n1; +} + + // ID, true, false, null +value(res) ::= ID(id). { + if (defined(id)) { + if ($this->security) { + $this->security->isTrustedConstant(id, $this->compiler); + } + res = id; + } else { + res = '\''.id.'\''; + } +} + + // function call +value(res) ::= function(f). { + res = f; +} + + // expression +value(res) ::= OPENP expr(e) CLOSEP. { + res = "(". e .")"; +} + + // singele quoted string +value(res) ::= SINGLEQUOTESTRING(t). { + res = t; +} + + // double quoted string +value(res) ::= doublequoted_with_quotes(s). { + res = s; +} + + +value(res) ::= varindexed(vi) DOUBLECOLON static_class_access(r). { + self::$prefix_number++; + if (vi['var'] == '\'smarty\'') { + $this->compiler->prefix_code[] = 'compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']).';?>'; + } else { + $this->compiler->prefix_code[] = 'compiler->compileVariable(vi['var']).vi['smarty_internal_index'].';?>'; + } + res = '$_tmp'.self::$prefix_number.'::'.r[0].r[1]; +} + + // Smarty tag +value(res) ::= smartytag(st). { + self::$prefix_number++; + $tmp = $this->compiler->appendCode('', st); + $this->compiler->prefix_code[] = $this->compiler->appendCode($tmp, ''); + res = '$_tmp'.self::$prefix_number; +} + +value(res) ::= value(v) modifierlist(l). { + res = $this->compiler->compileTag('private_modifier',array(),array('value'=>v,'modifierlist'=>l)); +} + // name space constant +value(res) ::= NAMESPACE(c). { + res = c; +} + + + // static class access +value(res) ::= ns1(c)DOUBLECOLON static_class_access(s). { + if (!in_array(strtolower(c), array('self', 'parent')) && (!$this->security || $this->security->isTrustedStaticClassAccess(c, s, $this->compiler))) { + if (isset($this->smarty->registered_classes[c])) { + res = $this->smarty->registered_classes[c].'::'.s[0].s[1]; + } else { + res = c.'::'.s[0].s[1]; + } + } else { + $this->compiler->trigger_template_error ("static class '".c."' is undefined or not allowed by security setting"); + } +} +// +// namespace stuff +// + +ns1(res) ::= ID(i). { + res = i; +} + +ns1(res) ::= NAMESPACE(i). { + res = i; +} + +//ns1(res) ::= variable(v). { +// res = v; +//} + + + + +// +// variables +// + // Smarty variable (optional array) +variable(res) ::= DOLLARID(i). { + res = $this->compiler->compileVariable('\''.substr(i,1).'\''); +} +variable(res) ::= varindexed(vi). { + if (vi['var'] == '\'smarty\'') { + $smarty_var = $this->compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']); + res = $smarty_var; + } else { + // used for array reset,next,prev,end,current + $this->last_variable = vi['var']; + $this->last_index = vi['smarty_internal_index']; + res = $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index']; + } +} + + // variable with property +variable(res) ::= varvar(v) AT ID(p). { + res = '$_smarty_tpl->tpl_vars['. v .']->'.p; +} + + // object +variable(res) ::= object(o). { + res = o; +} + + // config variable +variable(res) ::= HATCH ID(i) HATCH. { + res = '$_smarty_tpl->getConfigVariable( \''. i .'\')'; +} + +variable(res) ::= HATCH ID(i) HATCH arrayindex(a). { + res = '(is_array($tmp = $_smarty_tpl->getConfigVariable( \''. i .'\')) ? $tmp'.a.' :null)'; +} + +variable(res) ::= HATCH variable(v) HATCH. { + res = '$_smarty_tpl->getConfigVariable( '. v .')'; +} + +variable(res) ::= HATCH variable(v) HATCH arrayindex(a). { + res = '(is_array($tmp = $_smarty_tpl->getConfigVariable( '. v .')) ? $tmp'.a.' : null)'; +} + +varindexed(res) ::= DOLLARID(i) arrayindex(a). { + res = array('var'=>'\''.substr(i,1).'\'', 'smarty_internal_index'=>a); +} +varindexed(res) ::= varvar(v) arrayindex(a). { + res = array('var'=>v, 'smarty_internal_index'=>a); +} + +// +// array index +// + // multiple array index +arrayindex(res) ::= arrayindex(a1) indexdef(a2). { + res = a1.a2; +} + + // no array index +arrayindex ::= . { + return; +} + +// single index definition + // Smarty2 style index +indexdef(res) ::= DOT DOLLARID(i). { + res = '['.$this->compiler->compileVariable('\''.substr(i,1).'\'').']'; +} +indexdef(res) ::= DOT varvar(v). { + res = '['.$this->compiler->compileVariable(v).']'; +} + +indexdef(res) ::= DOT varvar(v) AT ID(p). { + res = '['.$this->compiler->compileVariable(v).'->'.p.']'; +} + +indexdef(res) ::= DOT ID(i). { + if (defined(i)) { + if ($this->security) { + $this->security->isTrustedConstant(i, $this->compiler); + } + res = '['. i .']'; + } else { + res = "['". i ."']"; + } +} + +indexdef(res) ::= DOT INTEGER(n). { + res = '['. n .']'; +} + +indexdef(res) ::= DOT LDEL expr(e) RDEL. { + res = '['. e .']'; +} + + // section tag index +indexdef(res) ::= OPENB ID(i)CLOSEB. { + res = '['.$this->compiler->compileTag('private_special_variable',array(),'[\'section\'][\''.i.'\'][\'index\']').']'; +} + +indexdef(res) ::= OPENB ID(i) DOT ID(i2) CLOSEB. { + res = '['.$this->compiler->compileTag('private_special_variable',array(),'[\'section\'][\''.i.'\'][\''.i2.'\']').']'; +} +indexdef(res) ::= OPENB SINGLEQUOTESTRING(s) CLOSEB. { + res = '['.s.']'; +} +indexdef(res) ::= OPENB INTEGER(n) CLOSEB. { + res = '['.n.']'; +} +indexdef(res) ::= OPENB DOLLARID(i) CLOSEB. { + res = '['.$this->compiler->compileVariable('\''.substr(i,1).'\'').']';; +} +indexdef(res) ::= OPENB variable(v) CLOSEB. { + res = '['.v.']'; +} +indexdef(res) ::= OPENB value(v) CLOSEB. { + res = '['.v.']'; +} + + // PHP style index +indexdef(res) ::= OPENB expr(e) CLOSEB. { + res = '['. e .']'; +} + + // for assign append array +indexdef(res) ::= OPENB CLOSEB. { + res = '[]'; +} + + +// +// variable variable names +// + + // singel identifier element +varvar(res) ::= DOLLARID(i). { + res = '\''.substr(i,1).'\''; +} + // single $ +varvar(res) ::= DOLLAR. { + res = "''"; +} + + // sequence of identifier elements +varvar(res) ::= varvar(v1) varvarele(v2). { + res = v1.'.'.v2; +} + + // fix sections of element +varvarele(res) ::= ID(s). { + res = '\''.s.'\''; +} + + // variable sections of element +varvarele(res) ::= LDEL expr(e) RDEL. { + res = '('.e.')'; +} + +// +// objects +// +object(res) ::= varindexed(vi) objectchain(oc). { + if (vi['var'] == '\'smarty\'') { + res = $this->compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']).oc; + } else { + res = $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'].oc; + } +} + + // single element +objectchain(res) ::= objectelement(oe). { + res = oe; +} + + // chain of elements +objectchain(res) ::= objectchain(oc) objectelement(oe). { + res = oc.oe; +} + + // variable +objectelement(res)::= PTR ID(i) arrayindex(a). { + if ($this->security && substr(i,0,1) == '_') { + $this->compiler->trigger_template_error (self::Err1); + } + res = '->'.i.a; +} + +objectelement(res)::= PTR varvar(v) arrayindex(a). { + if ($this->security) { + $this->compiler->trigger_template_error (self::Err2); + } + res = '->{'.$this->compiler->compileVariable(v).a.'}'; +} + +objectelement(res)::= PTR LDEL expr(e) RDEL arrayindex(a). { + if ($this->security) { + $this->compiler->trigger_template_error (self::Err2); + } + res = '->{'.e.a.'}'; +} + +objectelement(res)::= PTR ID(ii) LDEL expr(e) RDEL arrayindex(a). { + if ($this->security) { + $this->compiler->trigger_template_error (self::Err2); + } + res = '->{\''.ii.'\'.'.e.a.'}'; +} + + // method +objectelement(res)::= PTR method(f). { + res = '->'.f; +} + + +// +// function +// +function(res) ::= ns1(f) OPENP params(p) CLOSEP. { + if (!$this->security || $this->security->isTrustedPhpFunction(f, $this->compiler)) { + if (strcasecmp(f,'isset') === 0 || strcasecmp(f,'empty') === 0 || strcasecmp(f,'array') === 0 || is_callable(f)) { + $func_name = strtolower(f); + if ($func_name == 'isset') { + if (count(p) == 0) { + $this->compiler->trigger_template_error ('Illegal number of paramer in "isset()"'); + } + $par = implode(',',p); + if (strncasecmp($par,'$_smarty_tpl->getConfigVariable',strlen('$_smarty_tpl->getConfigVariable')) === 0) { + self::$prefix_number++; + $this->compiler->prefix_code[] = ''; + $isset_par = '$_tmp'.self::$prefix_number; + } else { + $isset_par=str_replace("')->value","',null,true,false)->value",$par); + } + res = f . "(". $isset_par .")"; + } elseif (in_array($func_name,array('empty','reset','current','end','prev','next'))){ + if (count(p) != 1) { + $this->compiler->trigger_template_error ('Illegal number of paramer in "empty()"'); + } + if ($func_name == 'empty') { + res = $func_name.'('.str_replace("')->value","',null,true,false)->value",p[0]).')'; + } else { + res = $func_name.'('.p[0].')'; + } + } else { + res = f . "(". implode(',',p) .")"; + } + } else { + $this->compiler->trigger_template_error ("unknown function \"" . f . "\""); + } + } +} + + +// +// method +// +method(res) ::= ID(f) OPENP params(p) CLOSEP. { + if ($this->security && substr(f,0,1) == '_') { + $this->compiler->trigger_template_error (self::Err1); + } + res = f . "(". implode(',',p) .")"; +} + +method(res) ::= DOLLARID(f) OPENP params(p) CLOSEP. { + if ($this->security) { + $this->compiler->trigger_template_error (self::Err2); + } + self::$prefix_number++; + $this->compiler->prefix_code[] = 'compiler->compileVariable('\''.substr(f,1).'\'').';?>'; + res = '$_tmp'.self::$prefix_number.'('. implode(',',p) .')'; +} + +// function/method parameter + // multiple parameters +params(res) ::= params(p) COMMA expr(e). { + res = array_merge(p,array(e)); +} + + // single parameter +params(res) ::= expr(e). { + res = array(e); +} + + // kein parameter +params(res) ::= . { + res = array(); +} + +// +// modifier +// +modifierlist(res) ::= modifierlist(l) modifier(m) modparameters(p). { + res = array_merge(l,array(array_merge(m,p))); +} + +modifierlist(res) ::= modifier(m) modparameters(p). { + res = array(array_merge(m,p)); +} + +modifier(res) ::= VERT AT ID(m). { + res = array(m); +} + +modifier(res) ::= VERT ID(m). { + res = array(m); +} + +// +// modifier parameter +// + // multiple parameter +modparameters(res) ::= modparameters(mps) modparameter(mp). { + res = array_merge(mps,mp); +} + + // no parameter +modparameters(res) ::= . { + res = array(); +} + + // parameter expression +modparameter(res) ::= COLON value(mp). { + res = array(mp); +} + +modparameter(res) ::= COLON array(mp). { + res = array(mp); +} + + // static class methode call +static_class_access(res) ::= method(m). { + res = array(m, '', 'method'); +} + + // static class methode call with object chainig +static_class_access(res) ::= method(m) objectchain(oc). { + res = array(m, oc, 'method'); +} + + // static class constant +static_class_access(res) ::= ID(v). { + res = array(v, ''); +} + + // static class variables +static_class_access(res) ::= DOLLARID(v) arrayindex(a). { + res = array(v, a, 'property'); +} + + // static class variables with object chain +static_class_access(res) ::= DOLLARID(v) arrayindex(a) objectchain(oc). { + res = array(v, a.oc, 'property'); +} + + +// if conditions and operators +lop(res) ::= LOGOP(o). { + res['op'] = ' '. trim(o) . ' '; +} + +lop(res) ::= TLOGOP(o). { + static $lops = array( + 'eq' => array('op' => ' == ', 'pre' => null), + 'ne' => array('op' => ' != ', 'pre' => null), + 'neq' => array('op' => ' != ', 'pre' => null), + 'gt' => array('op' => ' > ', 'pre' => null), + 'ge' => array('op' => ' >= ', 'pre' => null), + 'gte' => array('op' => ' >= ', 'pre' => null), + 'lt' => array('op' => ' < ', 'pre' => null), + 'le' => array('op' => ' <= ', 'pre' => null), + 'lte' => array('op' => ' <= ', 'pre' => null), + 'mod' => array('op' => ' % ', 'pre' => null), + 'and' => array('op' => ' && ', 'pre' => null), + 'or' => array('op' => ' || ', 'pre' => null), + 'xor' => array('op' => ' xor ', 'pre' => null), + 'isdivby' => array('op' => ' % ', 'pre' => '!('), + 'isnotdivby' => array('op' => ' % ', 'pre' => '('), + 'isevenby' => array('op' => ' / ', 'pre' => '!(1 & '), + 'isnotevenby' => array('op' => ' / ', 'pre' => '(1 & '), + 'isoddby' => array('op' => ' / ', 'pre' => '(1 & '), + 'isnotoddby' => array('op' => ' / ', 'pre' => '!(1 & '), + ); + $op = strtolower(preg_replace('/\s*/', '', o)); + res = $lops[$op]; +} + +scond(res) ::= SINGLECOND(o). { + static $scond = array ( + 'iseven' => '!(1 & ', + 'isnoteven' => '(1 & ', + 'isodd' => '(1 & ', + 'isnotodd' => '!(1 & ', + ); + $op = strtolower(str_replace(' ', '', o)); + res = $scond[$op]; +} + +// +// ARRAY element assignment +// +array(res) ::= OPENB arrayelements(a) CLOSEB. { + res = 'array('.a.')'; +} + +arrayelements(res) ::= arrayelement(a). { + res = a; +} + +arrayelements(res) ::= arrayelements(a1) COMMA arrayelement(a). { + res = a1.','.a; +} + +arrayelements ::= . { + return; +} + +arrayelement(res) ::= value(e1) APTR expr(e2). { + res = e1.'=>'.e2; +} + +arrayelement(res) ::= ID(i) APTR expr(e2). { + res = '\''.i.'\'=>'.e2; +} + +arrayelement(res) ::= expr(e). { + res = e; +} + + +// +// double qouted strings +// +doublequoted_with_quotes(res) ::= QUOTE QUOTE. { + res = "''"; +} + +doublequoted_with_quotes(res) ::= QUOTE doublequoted(s) QUOTE. { + res = s->to_smarty_php(); +} + + +doublequoted(res) ::= doublequoted(o1) doublequotedcontent(o2). { + o1->append_subtree(o2); + res = o1; +} + +doublequoted(res) ::= doublequotedcontent(o). { + res = new Smarty_Internal_ParseTree_Dq($this, o); +} + +doublequotedcontent(res) ::= BACKTICK variable(v) BACKTICK. { + res = new Smarty_Internal_ParseTree_Code($this, '(string)'.v); +} + +doublequotedcontent(res) ::= BACKTICK expr(e) BACKTICK. { + res = new Smarty_Internal_ParseTree_Code($this, '(string)'.e); +} + +doublequotedcontent(res) ::= DOLLARID(i). { + res = new Smarty_Internal_ParseTree_Code($this, '(string)$_smarty_tpl->tpl_vars[\''. substr(i,1) .'\']->value'); +} + +doublequotedcontent(res) ::= LDEL variable(v) RDEL. { + res = new Smarty_Internal_ParseTree_Code($this, '(string)'.v); +} + +doublequotedcontent(res) ::= LDEL expr(e) RDEL. { + res = new Smarty_Internal_ParseTree_Code($this, '(string)('.e.')'); +} + +doublequotedcontent(res) ::= smartytag(st). { + res = new Smarty_Internal_ParseTree_Tag($this, st); +} + +doublequotedcontent(res) ::= TEXT(o). { + res = new Smarty_Internal_ParseTree_DqContent($this, o); +} + diff --git a/library/Smarty/libs/Autoloader.php b/library/Smarty/libs/Autoloader.php new file mode 100644 index 000000000..a24cad6f7 --- /dev/null +++ b/library/Smarty/libs/Autoloader.php @@ -0,0 +1,158 @@ + '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; + } +} diff --git a/library/Smarty/libs/Smarty.class.php b/library/Smarty/libs/Smarty.class.php index 832b0d309..1f0f2634a 100644 --- a/library/Smarty/libs/Smarty.class.php +++ b/library/Smarty/libs/Smarty.class.php @@ -2,15 +2,17 @@ /** * Project: Smarty: the PHP compiling template engine * File: Smarty.class.php - * SVN: $Id: Smarty.class.php 4897 2014-10-14 22:29:58Z Uwe.Tews@googlemail.com $ + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -19,12 +21,13 @@ * smarty-discussion-subscribe@googlegroups.com * * @link http://www.smarty.net/ - * @copyright 2008 New Digital Group, Inc. + * @copyright 2015 New Digital Group, Inc. + * @copyright 2015 Uwe Tews * @author Monte Ohrt * @author Uwe Tews * @author Rodney Rehm * @package Smarty - * @version 3.1.21 + * @version 3.1.27 */ /** @@ -53,7 +56,7 @@ if (!defined('SMARTY_PLUGINS_DIR')) { define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DS); } if (!defined('SMARTY_MBSTRING')) { - define('SMARTY_MBSTRING', function_exists('mb_split')); + define('SMARTY_MBSTRING', function_exists('mb_get_info')); } if (!defined('SMARTY_RESOURCE_CHAR_SET')) { // UTF-8 can only be done properly when mbstring is available! @@ -70,31 +73,29 @@ if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) { } /** - * register the class autoloader + * Try loading the Smarty_Internal_Data class + * If we fail we must load Smarty's autoloader. + * Otherwise we may have a global autoloader like Composer */ -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(); +if (!class_exists('Smarty_Autoloader', false)) { + if (!class_exists('Smarty_Internal_Data', true)) { + require_once 'Autoloader.php'; + Smarty_Autoloader::registerBC(); } -} else { - spl_autoload_register('smartyAutoload'); } /** * Load always needed external class files */ -include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php'; -include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php'; -include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php'; -include_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php'; -include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_resource_file.php'; -include_once SMARTY_SYSPLUGINS_DIR . 'smarty_cacheresource.php'; -include_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_cacheresource_file.php'; + +if (!class_exists('Smarty_Internal_Data', false)) { + require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php'; +} +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php'; +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php'; +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php'; +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php'; +require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php'; /** * This is the main Smarty class @@ -110,21 +111,28 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = 'Smarty-3.1.21-dev'; + const SMARTY_VERSION = '3.1.27'; /** * define variable scopes */ const SCOPE_LOCAL = 0; + const SCOPE_PARENT = 1; + const SCOPE_ROOT = 2; + const SCOPE_GLOBAL = 3; + /** * define caching modes */ const CACHING_OFF = 0; + const CACHING_LIFETIME_CURRENT = 1; + const CACHING_LIFETIME_SAVED = 2; + /** * define constant for clearing cache files be saved expiration datees */ @@ -134,29 +142,53 @@ class Smarty extends Smarty_Internal_TemplateBase * define compile check modes */ const COMPILECHECK_OFF = 0; + const COMPILECHECK_ON = 1; + const COMPILECHECK_CACHEMISS = 2; + + /** + * define debug modes + */ + const DEBUG_OFF = 0; + + const DEBUG_ON = 1; + + const DEBUG_INDIVIDUAL = 2; + /** * modes for handling of "" tags in templates. */ const PHP_PASSTHRU = 0; //-> print tags as plain text + const PHP_QUOTE = 1; //-> escape tags as entities + const PHP_REMOVE = 2; //-> escape tags as entities + const PHP_ALLOW = 3; //-> escape tags as entities + /** * filter types */ const FILTER_POST = 'post'; + const FILTER_PRE = 'pre'; + const FILTER_OUTPUT = 'output'; + const FILTER_VARIABLE = 'variable'; + /** * plugin types */ const PLUGIN_FUNCTION = 'function'; + const PLUGIN_BLOCK = 'block'; + const PLUGIN_COMPILER = 'compiler'; + const PLUGIN_MODIFIER = 'modifier'; + const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler'; /**#@-*/ @@ -170,23 +202,28 @@ class Smarty extends Smarty_Internal_TemplateBase * error handler returned by set_error_hanlder() in Smarty::muteExpectedErrors() */ public static $_previous_error_handler = null; + /** * contains directories outside of SMARTY_DIR that are to be muted by muteExpectedErrors() */ - public static $_muted_directories = array(); + public static $_muted_directories = array('./templates_c/' => null, './cache/' => null); + /** * Flag denoting if Multibyte String functions are available */ public static $_MBSTRING = SMARTY_MBSTRING; + /** * The character set to adhere to (e.g. "UTF-8") */ public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET; + /** * The date format to be used internally * (accepts date() and strftime()) */ public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT; + /** * Flag denoting if PCRE should run in UTF-8 mode */ @@ -207,158 +244,154 @@ class Smarty extends Smarty_Internal_TemplateBase * @var boolean */ public $auto_literal = true; + /** * display error on not assigned variables * * @var boolean */ public $error_unassigned = false; + /** * look up relative filepaths in include_path * * @var boolean */ public $use_include_path = false; + /** * template directory * * @var array */ - private $template_dir = array(); + private $template_dir = array('./templates/'); + /** * joined template directory string used in cache keys * * @var string */ - public $joined_template_dir = null; + public $joined_template_dir = './templates/'; + /** * joined config directory string used in cache keys * * @var string */ - public $joined_config_dir = null; + public $joined_config_dir = './configs/'; + /** * default template handler * * @var callable */ public $default_template_handler_func = null; + /** * default config handler * * @var callable */ public $default_config_handler_func = null; + /** * default plugin handler * * @var callable */ public $default_plugin_handler_func = null; + /** * compile directory * * @var string */ - private $compile_dir = null; + private $compile_dir = './templates_c/'; + /** * plugins directory * * @var array */ - private $plugins_dir = array(); + private $plugins_dir = null; + /** * cache directory * * @var string */ - private $cache_dir = null; + private $cache_dir = './cache/'; + /** * config directory * * @var array */ - private $config_dir = array(); + private $config_dir = array('./configs/'); + /** * force template compiling? * * @var boolean */ public $force_compile = false; + /** * check template for modifications? * * @var boolean */ public $compile_check = true; + /** * use sub dirs for compiled/cached files? * * @var boolean */ public $use_sub_dirs = false; + /** * allow ambiguous resources (that are made unique by the resource handler) * * @var boolean */ public $allow_ambiguous_resources = false; - /** - * caching enabled - * - * @var boolean - */ - public $caching = false; + /** * merge compiled includes * * @var boolean */ public $merge_compiled_includes = false; + /** * template inheritance merge compiled includes * * @var boolean */ public $inheritance_merge_compiled_includes = true; - /** - * cache lifetime in seconds - * - * @var integer - */ - public $cache_lifetime = 3600; + /** * force cache file creation * * @var boolean */ public $force_cache = false; - /** - * Set this if you want different sets of cache files for the same - * templates. - * - * @var string - */ - public $cache_id = null; - /** - * Set this if you want different sets of compiled files for the same - * templates. - * - * @var string - */ - public $compile_id = null; + /** * template left-delimiter * * @var string */ public $left_delimiter = "{"; + /** * template right-delimiter * * @var string */ public $right_delimiter = "}"; + /**#@+ * security */ @@ -370,24 +403,28 @@ class Smarty extends Smarty_Internal_TemplateBase * @see Smarty_Security */ public $security_class = 'Smarty_Security'; + /** * implementation of security class * * @var Smarty_Security */ public $security_policy = null; + /** * controls handling of PHP-blocks * * @var integer */ public $php_handling = self::PHP_PASSTHRU; + /** * controls if the php template file resource is allowed * * @var bool */ public $allow_php_templates = false; + /** * Should compiled-templates be prevented from being called directly? * {@internal @@ -397,6 +434,7 @@ class Smarty extends Smarty_Internal_TemplateBase * @var boolean */ public $direct_access_security = true; + /**#@-*/ /** * debug mode @@ -405,6 +443,7 @@ class Smarty extends Smarty_Internal_TemplateBase * @var boolean */ public $debugging = false; + /** * This determines if debugging is enable-able from the browser. *
    @@ -415,26 +454,30 @@ class Smarty extends Smarty_Internal_TemplateBase * @var string */ public $debugging_ctrl = 'NONE'; + /** * Name of debugging URL-param. * Only used when $debugging_ctrl is set to 'URL'. * The name of the URL-parameter that activates debugging. * - * @var type + * @var string */ public $smarty_debug_id = 'SMARTY_DEBUG'; + /** * Path of debug template. * * @var string */ public $debug_tpl = null; + /** * When set, smarty uses this value as error_reporting-level. * * @var int */ public $error_reporting = null; + /** * Internal flag for getTags() * @@ -452,12 +495,14 @@ class Smarty extends Smarty_Internal_TemplateBase * @var boolean */ public $config_overwrite = true; + /** * Controls whether config values of on/true/yes and off/false/no get converted to boolean. * * @var boolean */ public $config_booleanize = true; + /** * Controls whether hidden config sections/vars are read from the file. * @@ -477,12 +522,14 @@ class Smarty extends Smarty_Internal_TemplateBase * @var boolean */ public $compile_locking = true; + /** * Controls whether cache resources should emply locking mechanism * * @var boolean */ public $cache_locking = false; + /** * seconds to wait for acquiring a lock before ignoring the write lock * @@ -492,12 +539,6 @@ class Smarty extends Smarty_Internal_TemplateBase /**#@-*/ - /** - * global template functions - * - * @var array - */ - public $template_functions = array(); /** * resource type used if none given * Must be an valid key of $registered_resources. @@ -505,6 +546,7 @@ class Smarty extends Smarty_Internal_TemplateBase * @var string */ public $default_resource_type = 'file'; + /** * caching type * Must be an element of $cache_resource_types. @@ -512,256 +554,284 @@ class Smarty extends Smarty_Internal_TemplateBase * @var string */ public $caching_type = 'file'; + /** * internal config properties * * @var array */ public $properties = array(); + /** * config type * * @var string */ public $default_config_type = 'file'; + + /** + * cached template objects + * + * @var array + */ + public $source_objects = array(); + /** * cached template objects * * @var array */ public $template_objects = array(); + + /** + * enable resource caching + * + * @var bool + */ + public $resource_caching = false; + + /** + * enable template resource caching + * + * @var bool + */ + public $template_resource_caching = true; + /** * check If-Modified-Since headers * * @var boolean */ public $cache_modified_check = false; + /** * registered plugins * * @var array */ public $registered_plugins = array(); + /** * plugin search order * * @var array */ public $plugin_search_order = array('function', 'block', 'compiler', 'class'); + /** * registered objects * * @var array */ public $registered_objects = array(); + /** * registered classes * * @var array */ public $registered_classes = array(); + /** * registered filters * * @var array */ public $registered_filters = array(); + /** * registered resources * * @var array */ public $registered_resources = array(); + /** * resource handler cache * * @var array */ public $_resource_handlers = array(); + /** * registered cache resources * * @var array */ public $registered_cache_resources = array(); + /** * cache resource handler cache * * @var array */ public $_cacheresource_handlers = array(); + /** * autoload filter * * @var array */ public $autoload_filters = array(); + /** * default modifier * * @var array */ public $default_modifiers = array(); + /** * autoescape variable output * * @var boolean */ public $escape_html = false; + /** * global internal smarty vars * * @var array */ public static $_smarty_vars = array(); + /** * start time for execution time calculation * * @var int */ public $start_time = 0; + /** * default file permissions * * @var int */ public $_file_perms = 0644; + /** * default dir permissions * * @var int */ public $_dir_perms = 0771; + /** * block tag hierarchy * * @var array */ public $_tag_stack = array(); - /** - * self pointer to Smarty object - * - * @var Smarty - */ - public $smarty; + /** * required by the compiler for BC * * @var string */ public $_current_file = null; + /** * internal flag to enable parser debugging * * @var bool */ public $_parserdebug = false; - /** - * Saved parameter of merged templates during compilation - * - * @var array - */ - public $merged_templates_func = array(); /** * Cache of is_file results of loadPlugin() - * + * * @var array */ - public static $_is_file_cache= array(); + public $_is_file_cache = array(); /**#@-*/ /** * Initialize new Smarty object - */ public function __construct() { - // selfpointer needed by some other class methods - $this->smarty = $this; if (is_callable('mb_internal_encoding')) { mb_internal_encoding(Smarty::$_CHARSET); } $this->start_time = microtime(true); - // set default dirs - $this->setTemplateDir('.' . DS . 'templates' . DS) - ->setCompileDir('.' . DS . 'templates_c' . DS) - ->setPluginsDir(SMARTY_PLUGINS_DIR) - ->setCacheDir('.' . DS . 'cache' . DS) - ->setConfigDir('.' . DS . 'configs' . DS); - - $this->debug_tpl = 'file:' . dirname(__FILE__) . '/debug.tpl'; + // check default dirs for overloading + if ($this->template_dir[0] !== './templates/' || isset($this->template_dir[1])) { + $this->setTemplateDir($this->template_dir); + } + if ($this->config_dir[0] !== './configs/' || isset($this->config_dir[1])) { + $this->setConfigDir($this->config_dir); + } + if ($this->compile_dir !== './templates_c/') { + unset(self::$_muted_directories['./templates_c/']); + $this->setCompileDir($this->compile_dir); + } + if ($this->cache_dir !== './cache/') { + unset(self::$_muted_directories['./cache/']); + $this->setCacheDir($this->cache_dir); + } + if (isset($this->plugins_dir)) { + $this->setPluginsDir($this->plugins_dir); + } else { + $this->setPluginsDir(SMARTY_PLUGINS_DIR); + } if (isset($_SERVER['SCRIPT_NAME'])) { - $this->assignGlobal('SCRIPT_NAME', $_SERVER['SCRIPT_NAME']); + Smarty::$global_tpl_vars['SCRIPT_NAME'] = new Smarty_Variable($_SERVER['SCRIPT_NAME']); } - } - /** - * Class destructor - */ - public function __destruct() - { - // intentionally left blank - } + // Check if we're running on windows + Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; - /** - * <> set selfpointer on cloned object - */ - public function __clone() - { - $this->smarty = $this; + // let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8 + if (Smarty::$_CHARSET !== 'UTF-8') { + Smarty::$_UTF8_MODIFIER = ''; + } } /** - * <> Generic getter. - * Calls the appropriate getter function. - * Issues an E_USER_NOTICE if no valid getter is found. + * fetches a rendered Smarty template * - * @param string $name property name + * @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 not used - left for BC + * @param bool $no_output_filter not used - left for BC * - * @return mixed + * @throws Exception + * @throws SmartyException + * @return string rendered template output */ - public function __get($name) + public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false) { - $allowed = array( - 'template_dir' => 'getTemplateDir', - 'config_dir' => 'getConfigDir', - 'plugins_dir' => 'getPluginsDir', - 'compile_dir' => 'getCompileDir', - 'cache_dir' => 'getCacheDir', - ); - - if (isset($allowed[$name])) { - return $this->{$allowed[$name]}(); - } else { - trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); + if ($cache_id !== null && is_object($cache_id)) { + $parent = $cache_id; + $cache_id = null; } + if ($parent === null) { + $parent = $this; + } + // get template object + $_template = is_object($template) ? $template : $this->createTemplate($template, $cache_id, $compile_id, $parent, false); + // set caching in template object + $_template->caching = $this->caching; + // fetch template content + return $_template->render(true, false, $display); } /** - * <> Generic setter. - * Calls the appropriate setter function. - * Issues an E_USER_NOTICE if no valid setter is found. + * displays a Smarty template * - * @param string $name property name - * @param mixed $value parameter passed to setter + * @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 */ - public function __set($name, $value) + public function display($template = null, $cache_id = null, $compile_id = null, $parent = null) { - $allowed = array( - 'template_dir' => 'setTemplateDir', - 'config_dir' => 'setConfigDir', - 'plugins_dir' => 'setPluginsDir', - 'compile_dir' => 'setCompileDir', - 'cache_dir' => 'setCacheDir', - ); - - if (isset($allowed[$name])) { - $this->{$allowed[$name]}($value); - } else { - trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); - } + // display template + $this->fetch($template, $cache_id, $compile_id, $parent, true); } /** @@ -899,11 +969,9 @@ class Smarty extends Smarty_Internal_TemplateBase { $this->template_dir = array(); foreach ((array) $template_dir as $k => $v) { - $this->template_dir[$k] = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($v, '/\\')) . DS; + $this->template_dir[$k] = rtrim($v, '/\\') . DS; } - - $this->joined_template_dir = join(DIRECTORY_SEPARATOR, $this->template_dir); - + $this->joined_template_dir = join(' # ', $this->template_dir); return $this; } @@ -918,32 +986,8 @@ class Smarty extends Smarty_Internal_TemplateBase */ public function addTemplateDir($template_dir, $key = null) { - // make sure we're dealing with an array - $this->template_dir = (array) $this->template_dir; - - if (is_array($template_dir)) { - foreach ($template_dir as $k => $v) { - $v = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($v, '/\\')) . DS; - if (is_int($k)) { - // indexes are not merged but appended - $this->template_dir[] = $v; - } else { - // string indexes are overridden - $this->template_dir[$k] = $v; - } - } - } else { - $v = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($template_dir, '/\\')) . DS; - if ($key !== null) { - // override directory at specified index - $this->template_dir[$key] = $v; - } else { - // append new directory - $this->template_dir[] = $v; - } - } - $this->joined_template_dir = join(DIRECTORY_SEPARATOR, $this->template_dir); - + $this->_addDir('template_dir', $template_dir, $key); + $this->joined_template_dir = join(' # ', $this->template_dir); return $this; } @@ -959,7 +1003,6 @@ class Smarty extends Smarty_Internal_TemplateBase if ($index !== null) { return isset($this->template_dir[$index]) ? $this->template_dir[$index] : null; } - return (array) $this->template_dir; } @@ -974,51 +1017,24 @@ class Smarty extends Smarty_Internal_TemplateBase { $this->config_dir = array(); foreach ((array) $config_dir as $k => $v) { - $this->config_dir[$k] = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($v, '/\\')) . DS; + $this->config_dir[$k] = rtrim($v, '/\\') . DS; } - - $this->joined_config_dir = join(DIRECTORY_SEPARATOR, $this->config_dir); - + $this->joined_config_dir = join(' # ', $this->config_dir); return $this; } /** * Add config directory(s) * - * @param string|array $config_dir directory(s) of config sources - * @param mixed $key key of the array element to assign the config dir to + * @param string|array $config_dir directory(s) of config sources + * @param mixed $key key of the array element to assign the config dir to * * @return Smarty current Smarty instance for chaining */ public function addConfigDir($config_dir, $key = null) { - // make sure we're dealing with an array - $this->config_dir = (array) $this->config_dir; - - if (is_array($config_dir)) { - foreach ($config_dir as $k => $v) { - $v = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($v, '/\\')) . DS; - if (is_int($k)) { - // indexes are not merged but appended - $this->config_dir[] = $v; - } else { - // string indexes are overridden - $this->config_dir[$k] = $v; - } - } - } else { - $v = preg_replace('#(\w+)(/|\\\\){1,}#', '$1$2', rtrim($config_dir, '/\\')) . DS; - if ($key !== null) { - // override directory at specified index - $this->config_dir[$key] = rtrim($v, '/\\') . DS; - } else { - // append new directory - $this->config_dir[] = rtrim($v, '/\\') . DS; - } - } - - $this->joined_config_dir = join(DIRECTORY_SEPARATOR, $this->config_dir); - + $this->_addDir('config_dir', $config_dir, $key); + $this->joined_config_dir = join(' # ', $this->config_dir); return $this; } @@ -1034,7 +1050,6 @@ class Smarty extends Smarty_Internal_TemplateBase if ($index !== null) { return isset($this->config_dir[$index]) ? $this->config_dir[$index] : null; } - return (array) $this->config_dir; } @@ -1048,10 +1063,7 @@ class Smarty extends Smarty_Internal_TemplateBase public function setPluginsDir($plugins_dir) { $this->plugins_dir = array(); - foreach ((array) $plugins_dir as $k => $v) { - $this->plugins_dir[$k] = rtrim($v, '/\\') . DS; - } - + $this->addPluginsDir($plugins_dir); return $this; } @@ -1066,24 +1078,11 @@ class Smarty extends Smarty_Internal_TemplateBase { // make sure we're dealing with an array $this->plugins_dir = (array) $this->plugins_dir; - - if (is_array($plugins_dir)) { - foreach ($plugins_dir as $k => $v) { - if (is_int($k)) { - // indexes are not merged but appended - $this->plugins_dir[] = rtrim($v, '/\\') . DS; - } else { - // string indexes are overridden - $this->plugins_dir[$k] = rtrim($v, '/\\') . DS; - } - } - } else { - // append new directory - $this->plugins_dir[] = rtrim($plugins_dir, '/\\') . DS; + foreach ((array) $plugins_dir as $v) { + $this->plugins_dir[] = rtrim($v, '/\\') . DS; } - $this->plugins_dir = array_unique($this->plugins_dir); - + $this->_is_file_cache = array(); return $this; } @@ -1137,7 +1136,6 @@ class Smarty extends Smarty_Internal_TemplateBase if (!isset(Smarty::$_muted_directories[$this->cache_dir])) { Smarty::$_muted_directories[$this->cache_dir] = null; } - return $this; } @@ -1151,6 +1149,39 @@ class Smarty extends Smarty_Internal_TemplateBase return $this->cache_dir; } + /** + * add directories to given property name + * + * @param string $dirName directory property name + * @param string|array $dir directory string or array of strings + * @param mixed $key optional key + */ + private function _addDir($dirName, $dir, $key = null) + { + // make sure we're dealing with an array + $this->$dirName = (array) $this->$dirName; + + if (is_array($dir)) { + foreach ($dir as $k => $v) { + if (is_int($k)) { + // indexes are not merged but appended + $this->{$dirName}[] = rtrim($v, '/\\') . DS; + } else { + // string indexes are overridden + $this->{$dirName}[$k] = rtrim($v, '/\\') . DS; + } + } + } else { + if ($key !== null) { + // override directory at specified index + $this->{$dirName}[$key] = rtrim($dir, '/\\') . DS; + } else { + // append new directory + $this->{$dirName}[] = rtrim($dir, '/\\') . DS; + } + } + } + /** * Set default modifiers * @@ -1197,7 +1228,8 @@ class Smarty extends Smarty_Internal_TemplateBase * Set autoload filters * * @param array $filters filters to load automatically - * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters' keys as the appropriate types + * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters' + * keys as the appropriate types * * @return Smarty current Smarty instance for chaining */ @@ -1216,7 +1248,8 @@ class Smarty extends Smarty_Internal_TemplateBase * Add autoload filters * * @param array $filters filters to load automatically - * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters' keys as the appropriate types + * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters' + * keys as the appropriate types * * @return Smarty current Smarty instance for chaining */ @@ -1246,7 +1279,8 @@ class Smarty extends Smarty_Internal_TemplateBase * * @param string $type type of filter to get autoloads for. Defaults to all autoload filters * - * @return array array( 'type1' => array( 'filter1', 'filter2', … ) ) or array( 'filter1', 'filter2', …) if $type was specified + * @return array array( 'type1' => array( 'filter1', 'filter2', … ) ) or array( 'filter1', 'filter2', …) if $type + * was specified */ public function getAutoloadFilters($type = null) { @@ -1308,48 +1342,34 @@ class Smarty extends Smarty_Internal_TemplateBase } else { $data = null; } - // default to cache_id and compile_id of Smarty object - $cache_id = $cache_id === null ? $this->cache_id : $cache_id; - $compile_id = $compile_id === null ? $this->compile_id : $compile_id; - // already in template cache? - if ($this->allow_ambiguous_resources) { - $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template) . $cache_id . $compile_id; - } else { - $_templateId = $this->joined_template_dir . '#' . $template . $cache_id . $compile_id; - } - if (isset($_templateId[150])) { - $_templateId = sha1($_templateId); - } - if ($do_clone) { - if (isset($this->template_objects[$_templateId])) { - // return cached template object + $_templateId = $this->getTemplateId($template, $cache_id, $compile_id); + if (isset($this->template_objects[$_templateId])) { + if ($do_clone) { $tpl = clone $this->template_objects[$_templateId]; $tpl->smarty = clone $tpl->smarty; - $tpl->parent = $parent; - $tpl->tpl_vars = array(); - $tpl->config_vars = array(); } else { - $tpl = new $this->template_class($template, clone $this, $parent, $cache_id, $compile_id); + $tpl = $this->template_objects[$_templateId]; } + $tpl->parent = $parent; + $tpl->tpl_vars = array(); + $tpl->config_vars = array(); } else { - if (isset($this->template_objects[$_templateId])) { - // return cached template object - $tpl = $this->template_objects[$_templateId]; - $tpl->parent = $parent; - $tpl->tpl_vars = array(); - $tpl->config_vars = array(); - } else { - $tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id); + $tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id); + if ($do_clone) { + $tpl->smarty = clone $tpl->smarty; } + $tpl->templateId = $_templateId; } // fill data if present if (!empty($data) && is_array($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); } } - + if ($this->debugging) { + Smarty_Internal_Debug::register_template($tpl); + } return $tpl; } @@ -1380,7 +1400,7 @@ class Smarty extends Smarty_Internal_TemplateBase // if type is "internal", get plugin from sysplugins if (strtolower($_name_parts[1]) == 'internal') { $file = SMARTY_SYSPLUGINS_DIR . strtolower($plugin_name) . '.php'; - if (isset(self::$_is_file_cache[$file]) ? self::$_is_file_cache[$file] : self::$_is_file_cache[$file] = is_file($file)) { + if (isset($this->_is_file_cache[$file]) ? $this->_is_file_cache[$file] : $this->_is_file_cache[$file] = is_file($file)) { require_once($file); return $file; } else { @@ -1394,12 +1414,9 @@ class Smarty extends Smarty_Internal_TemplateBase // loop through plugin dirs and find the plugin foreach ($this->getPluginsDir() as $_plugin_dir) { - $names = array( - $_plugin_dir . $_plugin_filename, - $_plugin_dir . strtolower($_plugin_filename), - ); + $names = array($_plugin_dir . $_plugin_filename, $_plugin_dir . strtolower($_plugin_filename),); foreach ($names as $file) { - if (isset(self::$_is_file_cache[$file]) ? self::$_is_file_cache[$file] : self::$_is_file_cache[$file] = is_file($file)) { + if (isset($this->_is_file_cache[$file]) ? $this->_is_file_cache[$file] : $this->_is_file_cache[$file] = is_file($file)) { require_once($file); return $file; } @@ -1488,7 +1505,202 @@ class Smarty extends Smarty_Internal_TemplateBase */ public function testInstall(&$errors = null) { - return Smarty_Internal_Utility::testInstall($this, $errors); + return Smarty_Internal_TestInstall::testInstall($this, $errors); + } + + /** + * @param boolean $compile_check + */ + public function setCompileCheck($compile_check) + { + $this->compile_check = $compile_check; + } + + /** + * @param boolean $use_sub_dirs + */ + public function setUseSubDirs($use_sub_dirs) + { + $this->use_sub_dirs = $use_sub_dirs; + } + + /** + * @param boolean $caching + */ + public function setCaching($caching) + { + $this->caching = $caching; + } + + /** + * @param int $cache_lifetime + */ + public function setCacheLifetime($cache_lifetime) + { + $this->cache_lifetime = $cache_lifetime; + } + + /** + * @param string $compile_id + */ + public function setCompileId($compile_id) + { + $this->compile_id = $compile_id; + } + + /** + * @param string $cache_id + */ + public function setCacheId($cache_id) + { + $this->cache_id = $cache_id; + } + + /** + * @param int $error_reporting + */ + public function setErrorReporting($error_reporting) + { + $this->error_reporting = $error_reporting; + } + + /** + * @param boolean $escape_html + */ + public function setEscapeHtml($escape_html) + { + $this->escape_html = $escape_html; + } + + /** + * @param boolean $auto_literal + */ + public function setAutoLiteral($auto_literal) + { + $this->auto_literal = $auto_literal; + } + + /** + * @param boolean $force_compile + */ + public function setForceCompile($force_compile) + { + $this->force_compile = $force_compile; + } + + /** + * @param boolean $merge_compiled_includes + */ + public function setMergeCompiledIncludes($merge_compiled_includes) + { + $this->merge_compiled_includes = $merge_compiled_includes; + } + + /** + * @param string $left_delimiter + */ + public function setLeftDelimiter($left_delimiter) + { + $this->left_delimiter = $left_delimiter; + } + + /** + * @param string $right_delimiter + */ + public function setRightDelimiter($right_delimiter) + { + $this->right_delimiter = $right_delimiter; + } + + /** + * @param boolean $debugging + */ + public function setDebugging($debugging) + { + $this->debugging = $debugging; + } + + /** + * @param boolean $config_overwrite + */ + public function setConfigOverwrite($config_overwrite) + { + $this->config_overwrite = $config_overwrite; + } + + /** + * @param boolean $config_booleanize + */ + public function setConfigBooleanize($config_booleanize) + { + $this->config_booleanize = $config_booleanize; + } + + /** + * @param boolean $config_read_hidden + */ + public function setConfigReadHidden($config_read_hidden) + { + $this->config_read_hidden = $config_read_hidden; + } + + /** + * @param boolean $compile_locking + */ + public function setCompileLocking($compile_locking) + { + $this->compile_locking = $compile_locking; + } + + /** + * Class destructor + */ + public function __destruct() + { + // intentionally left blank + } + + /** + * <> Generic getter. + * Calls the appropriate getter function. + * Issues an E_USER_NOTICE if no valid getter is found. + * + * @param string $name property name + * + * @return mixed + */ + public function __get($name) + { + $allowed = array('template_dir' => 'getTemplateDir', 'config_dir' => 'getConfigDir', + 'plugins_dir' => 'getPluginsDir', 'compile_dir' => 'getCompileDir', + 'cache_dir' => 'getCacheDir',); + + if (isset($allowed[$name])) { + return $this->{$allowed[$name]}(); + } else { + trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); + } + } + + /** + * <> Generic setter. + * Calls the appropriate setter function. + * Issues an E_USER_NOTICE if no valid setter is found. + * + * @param string $name property name + * @param mixed $value parameter passed to setter + */ + public function __set($name, $value) + { + $allowed = array('template_dir' => 'setTemplateDir', 'config_dir' => 'setConfigDir', + 'plugins_dir' => 'setPluginsDir', 'compile_dir' => 'setCompileDir', + 'cache_dir' => 'setCacheDir',); + + if (isset($allowed[$name])) { + $this->{$allowed[$name]}($value); + } else { + trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); + } } /** @@ -1512,10 +1724,8 @@ class Smarty extends Smarty_Internal_TemplateBase if (!isset(Smarty::$_muted_directories[SMARTY_DIR])) { $smarty_dir = realpath(SMARTY_DIR); if ($smarty_dir !== false) { - Smarty::$_muted_directories[SMARTY_DIR] = array( - 'file' => $smarty_dir, - 'length' => strlen($smarty_dir), - ); + Smarty::$_muted_directories[SMARTY_DIR] = array('file' => $smarty_dir, + 'length' => strlen($smarty_dir),); } } @@ -1529,10 +1739,7 @@ class Smarty extends Smarty_Internal_TemplateBase unset(Smarty::$_muted_directories[$key]); continue; } - $dir = array( - 'file' => $file, - 'length' => strlen($file), - ); + $dir = array('file' => $file, 'length' => strlen($file),); } if (!strncmp($errfile, $dir['file'], $dir['length'])) { $_is_muted_directory = true; @@ -1593,88 +1800,3 @@ class Smarty extends Smarty_Internal_TemplateBase restore_error_handler(); } } - -// Check if we're running on windows -Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; - -// let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8 -if (Smarty::$_CHARSET !== 'UTF-8') { - Smarty::$_UTF8_MODIFIER = ''; -} - -/** - * 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) . ' <-- '; - } -} - -/** - * 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; -} - -/** - * Autoloader - */ -function smartyAutoload($class) -{ - $_class = strtolower($class); - static $_classes = array( - 'smarty_config_source' => true, - 'smarty_config_compiled' => true, - 'smarty_security' => true, - 'smarty_cacheresource' => true, - 'smarty_cacheresource_custom' => true, - 'smarty_cacheresource_keyvaluestore' => true, - 'smarty_resource' => true, - 'smarty_resource_custom' => true, - 'smarty_resource_uncompiled' => true, - 'smarty_resource_recompiled' => true, - ); - - if (!strncmp($_class, 'smarty_internal_', 16) || isset($_classes[$_class])) { - include SMARTY_SYSPLUGINS_DIR . $_class . '.php'; - } -} diff --git a/library/Smarty/libs/SmartyBC.class.php b/library/Smarty/libs/SmartyBC.class.php index cec946746..76dd8bd0f 100644 --- a/library/Smarty/libs/SmartyBC.class.php +++ b/library/Smarty/libs/SmartyBC.class.php @@ -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 ''; -} diff --git a/library/Smarty/libs/debug.tpl b/library/Smarty/libs/debug.tpl index 61b8876a4..5b09c5bd2 100644 --- a/library/Smarty/libs/debug.tpl +++ b/library/Smarty/libs/debug.tpl @@ -5,7 +5,7 @@ Smarty Debug Console