diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eb151bf..fbe0e7d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixes +- Adapt Smarty upper/lower functions to be codesafe (e.g. for Turkish locale) [#586](https://github.com/smarty-php/smarty/pull/586) + ## [3.1.36] - 2020-04-14 ### Fixed diff --git a/libs/Autoloader.php b/libs/Autoloader.php index 2de24a6c..128e475d 100644 --- a/libs/Autoloader.php +++ b/libs/Autoloader.php @@ -5,6 +5,11 @@ * @package Smarty */ + +if (!defined('SMARTY_HELPER_FUNCTIONS_LOADED')) { + include dirname(__FILE__) . '/functions.php'; +} + /** * Smarty Autoloader * diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 44589328..f89edaaa 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -74,12 +74,21 @@ if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) { */ define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y'); } + +/** + * Load helper functions + */ +if (!defined('SMARTY_HELPER_FUNCTIONS_LOADED')) { + include dirname(__FILE__) . '/functions.php'; +} + /** * Load Smarty_Autoloader */ if (!class_exists('Smarty_Autoloader')) { include dirname(__FILE__) . '/bootstrap.php'; } + /** * Load always needed external class files */ diff --git a/libs/functions.php b/libs/functions.php new file mode 100644 index 00000000..44bce6ed --- /dev/null +++ b/libs/functions.php @@ -0,0 +1,45 @@ +caching_type; } - $typeUcfirst = strtr(substr($type,0,1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') . substr($type,1); // try smarty's cache if (isset($smarty->_cache[ 'cacheresource_handlers' ][ $type ])) { return $smarty->_cache[ 'cacheresource_handlers' ][ $type ]; @@ -206,11 +205,11 @@ abstract class Smarty_CacheResource } // try sysplugins dir if (isset(self::$sysplugins[ $type ])) { - $cache_resource_class = 'Smarty_Internal_CacheResource_' . $typeUcfirst; + $cache_resource_class = 'Smarty_Internal_CacheResource_' . smarty_ucfirst_ascii($type); return $smarty->_cache[ 'cacheresource_handlers' ][ $type ] = new $cache_resource_class(); } // try plugins dir - $cache_resource_class = 'Smarty_CacheResource_' . $typeUcfirst; + $cache_resource_class = 'Smarty_CacheResource_' . smarty_ucfirst_ascii($type); if ($smarty->loadPlugin($cache_resource_class)) { return $smarty->_cache[ 'cacheresource_handlers' ][ $type ] = new $cache_resource_class(); } diff --git a/libs/sysplugins/smarty_internal_compile_private_foreachsection.php b/libs/sysplugins/smarty_internal_compile_private_foreachsection.php index 5c09b6e8..3893b652 100644 --- a/libs/sysplugins/smarty_internal_compile_private_foreachsection.php +++ b/libs/sysplugins/smarty_internal_compile_private_foreachsection.php @@ -143,8 +143,7 @@ class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_Com foreach ($this->resultOffsets as $key => $offset) { foreach ($match[ $offset ] as $m) { if (!empty($m)) { - $m = strtr($m, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); - $this->matchResults[ $key ][ $m ] = true; + $this->matchResults[ $key ][ smarty_strtolower_ascii($m) ] = true; } } } @@ -214,12 +213,12 @@ class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_Com */ public function compileSpecialVariable($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter) { - $tag = strtr(trim($parameter[ 0 ], '"\''), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); + $tag = smarty_strtolower_ascii(trim($parameter[ 0 ], '"\'')); $name = isset($parameter[ 1 ]) ? $compiler->getId($parameter[ 1 ]) : false; if (!$name) { $compiler->trigger_template_error("missing or illegal \$smarty.{$tag} name attribute", null, true); } - $property = isset($parameter[ 2 ]) ? strtr($compiler->getId($parameter[ 2 ]), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') : false; + $property = isset($parameter[ 2 ]) ? smarty_strtolower_ascii($compiler->getId($parameter[ 2 ])) : false; if (!$property || !in_array($property, $this->nameProperties)) { $compiler->trigger_template_error("missing or illegal \$smarty.{$tag} property attribute", null, true); } diff --git a/libs/sysplugins/smarty_internal_compile_private_special_variable.php b/libs/sysplugins/smarty_internal_compile_private_special_variable.php index 62900767..2683bff7 100644 --- a/libs/sysplugins/smarty_internal_compile_private_special_variable.php +++ b/libs/sysplugins/smarty_internal_compile_private_special_variable.php @@ -29,7 +29,7 @@ class Smarty_Internal_Compile_Private_Special_Variable extends Smarty_Internal_C public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter) { $_index = preg_split("/\]\[/", substr($parameter, 1, strlen($parameter) - 2)); - $variable = strtr($compiler->getId($_index[ 0 ]), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); + $variable = smarty_strtolower_ascii($compiler->getId($_index[ 0 ])); if ($variable === false) { $compiler->trigger_template_error("special \$Smarty variable name index can not be variable", null, true); } @@ -40,8 +40,7 @@ class Smarty_Internal_Compile_Private_Special_Variable extends Smarty_Internal_C case 'foreach': case 'section': if (!isset(Smarty_Internal_TemplateCompilerBase::$_tag_objects[ $variable ])) { - $variableUcfirst = strtr(substr($variable,0,1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') . substr($variable,1); - $class = 'Smarty_Internal_Compile_' . $variableUcfirst; + $class = 'Smarty_Internal_Compile_' . smarty_ucfirst_ascii($variable); Smarty_Internal_TemplateCompilerBase::$_tag_objects[ $variable ] = new $class; } return Smarty_Internal_TemplateCompilerBase::$_tag_objects[ $variable ]->compileSpecialVariable( @@ -77,8 +76,7 @@ class Smarty_Internal_Compile_Private_Special_Variable extends Smarty_Internal_C $compiler->trigger_template_error("(secure mode) super globals not permitted"); break; } - $variableUpper = strtr($variable, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'); - $compiled_ref = '$_' . $variableUpper; + $compiled_ref = '$_' . smarty_strtoupper_ascii($variable); break; case 'template': return 'basename($_smarty_tpl->source->filepath)'; diff --git a/libs/sysplugins/smarty_internal_extension_handler.php b/libs/sysplugins/smarty_internal_extension_handler.php index 5d412ebf..7de9f3f4 100644 --- a/libs/sysplugins/smarty_internal_extension_handler.php +++ b/libs/sysplugins/smarty_internal_extension_handler.php @@ -88,21 +88,19 @@ class Smarty_Internal_Extension_Handler $objType = $data->_objType; $propertyType = false; if (!isset($this->resolvedProperties[ $match[ 0 ] ][ $objType ])) { - $property = isset($this->resolvedProperties[ 'property' ][ $basename ]) ? - $this->resolvedProperties[ 'property' ][ $basename ] : - $property = $this->resolvedProperties[ 'property' ][ $basename ] = strtr( - join( - '_', - preg_split( - '/([A-Z][^A-Z]*)/', - $basename, - -1, - PREG_SPLIT_NO_EMPTY | - PREG_SPLIT_DELIM_CAPTURE - ) - ), - 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz' - ); + $property = $this->resolvedProperties['property'][$basename] ?? + $this->resolvedProperties['property'][$basename] = smarty_strtolower_ascii( + join( + '_', + preg_split( + '/([A-Z][^A-Z]*)/', + $basename, + -1, + PREG_SPLIT_NO_EMPTY | + PREG_SPLIT_DELIM_CAPTURE + ) + ) + ); if ($property !== false) { if (property_exists($data, $property)) { $propertyType = $this->resolvedProperties[ $match[ 0 ] ][ $objType ] = 1; @@ -146,9 +144,7 @@ class Smarty_Internal_Extension_Handler public function upperCase($name) { $_name = explode('_', $name); - foreach ($_name as &$namePart) { - $namePart = strtr(substr($namePart,0,1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') . substr($namePart,1); - } + $_name = array_map('smarty_ucfirst_ascii', $_name); return implode('_', $_name); } diff --git a/libs/sysplugins/smarty_internal_method_loadplugin.php b/libs/sysplugins/smarty_internal_method_loadplugin.php index 03817178..d301c28d 100644 --- a/libs/sysplugins/smarty_internal_method_loadplugin.php +++ b/libs/sysplugins/smarty_internal_method_loadplugin.php @@ -40,7 +40,7 @@ class Smarty_Internal_Method_LoadPlugin throw new SmartyException("plugin {$plugin_name} is not a valid name format"); } if (!empty($match[ 2 ])) { - $file = SMARTY_SYSPLUGINS_DIR . strtr($plugin_name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') . '.php'; + $file = SMARTY_SYSPLUGINS_DIR . smarty_strtolower_ascii($plugin_name) . '.php'; if (isset($this->plugin_files[ $file ])) { if ($this->plugin_files[ $file ] !== false) { return $this->plugin_files[ $file ]; @@ -60,7 +60,7 @@ class Smarty_Internal_Method_LoadPlugin } // plugin filename is expected to be: [type].[name].php $_plugin_filename = "{$match[1]}.{$match[4]}.php"; - $_lower_filename = strtr($_plugin_filename, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); + $_lower_filename = smarty_strtolower_ascii($_plugin_filename); if (isset($this->plugin_files)) { if (isset($this->plugin_files[ 'plugins_dir' ][ $_lower_filename ])) { if (!$smarty->use_include_path || $this->plugin_files[ 'plugins_dir' ][ $_lower_filename ] !== false) { diff --git a/libs/sysplugins/smarty_internal_templatecompilerbase.php b/libs/sysplugins/smarty_internal_templatecompilerbase.php index 81e84af7..879f685a 100644 --- a/libs/sysplugins/smarty_internal_templatecompilerbase.php +++ b/libs/sysplugins/smarty_internal_templatecompilerbase.php @@ -620,7 +620,7 @@ abstract class Smarty_Internal_TemplateCompilerBase if (strcasecmp($name, 'isset') === 0 || strcasecmp($name, 'empty') === 0 || strcasecmp($name, 'array') === 0 || is_callable($name) ) { - $func_name = strtr($name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'); + $func_name = smarty_strtolower_ascii($name); if ($func_name === 'isset') { if (count($parameter) === 0) { @@ -784,9 +784,7 @@ abstract class Smarty_Internal_TemplateCompilerBase if (!isset(self::$_tag_objects[ $tag ])) { // lazy load internal compiler plugin $_tag = explode('_', $tag); - foreach ($_tag as &$tagPart) { - $tagPart = strtr(substr($tagPart,0,1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') . substr($tagPart,1); - } + $_tag = array_map('smarty_ucfirst_ascii', $_tag); $class_name = 'Smarty_Internal_Compile_' . implode('_', $_tag); if (class_exists($class_name) && (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) diff --git a/libs/sysplugins/smarty_resource.php b/libs/sysplugins/smarty_resource.php index 7f82ed29..b3212033 100644 --- a/libs/sysplugins/smarty_resource.php +++ b/libs/sysplugins/smarty_resource.php @@ -76,14 +76,13 @@ abstract class Smarty_Resource $smarty->registered_resources[ $type ] instanceof Smarty_Resource ? $smarty->registered_resources[ $type ] : new Smarty_Internal_Resource_Registered(); } - $typeUcfirst = strtr(substr($type,0,1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') . substr($type,1); // try sysplugins dir if (isset(self::$sysplugins[ $type ])) { - $_resource_class = 'Smarty_Internal_Resource_' . $typeUcfirst; + $_resource_class = 'Smarty_Internal_Resource_' . smarty_ucfirst_ascii($type); return $smarty->_cache[ 'resource_handlers' ][ $type ] = new $_resource_class(); } // try plugins dir - $_resource_class = 'Smarty_Resource_' . $typeUcfirst; + $_resource_class = 'Smarty_Resource_' . smarty_ucfirst_ascii($type); if ($smarty->loadPlugin($_resource_class)) { if (class_exists($_resource_class, false)) { return $smarty->_cache[ 'resource_handlers' ][ $type ] = new $_resource_class();