diff --git a/CHANGELOG.md b/CHANGELOG.md index f9d10a750..8d7ef8199 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix Variable Usage in Exception message when unable to load subtemplate [#808](https://github.com/smarty-php/smarty/pull/808) - Fixed PHP8.1 deprecation notices for strftime [#672](https://github.com/smarty-php/smarty/issues/672) - Fixed PHP8.1 deprecation errors passing null to parameter in trim [#807](https://github.com/smarty-php/smarty/pull/807) +- Adapt Smarty upper/lower functions to be codesafe (e.g. for Turkish locale) [#586](https://github.com/smarty-php/smarty/pull/586) ## [4.2.1] - 2022-09-14 diff --git a/libs/Autoloader.php b/libs/Autoloader.php index 1673ce2ff..c20814031 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 * @@ -89,7 +94,7 @@ public static function autoload($class) if ($class[ 0 ] !== 'S' || strpos($class, 'Smarty') !== 0) { return; } - $_class = strtolower($class); + $_class = smarty_strtolower_ascii($class); if (isset(self::$rootClasses[ $_class ])) { $file = self::$SMARTY_DIR . self::$rootClasses[ $_class ]; if (is_file($file)) { diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 21beafdf0..5507ebcde 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -60,12 +60,21 @@ */ define('SMARTY_MBSTRING', function_exists('mb_get_info')); } + +/** + * 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 000000000..bac00e521 --- /dev/null +++ b/libs/functions.php @@ -0,0 +1,51 @@ +_cache[ 'cacheresource_handlers' ][ $type ] = new $cache_resource_class(); } // try plugins dir - $cache_resource_class = 'Smarty_CacheResource_' . ucfirst($type); + $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 d3aab24bb..246350dc8 100644 --- a/libs/sysplugins/smarty_internal_compile_private_foreachsection.php +++ b/libs/sysplugins/smarty_internal_compile_private_foreachsection.php @@ -143,7 +143,7 @@ public function matchProperty($source) foreach ($this->resultOffsets as $key => $offset) { foreach ($match[ $offset ] as $m) { if (!empty($m)) { - $this->matchResults[ $key ][ strtolower($m) ] = true; + $this->matchResults[ $key ][ smarty_strtolower_ascii($m) ] = true; } } } @@ -213,12 +213,12 @@ public function matchBlockSource(Smarty_Internal_TemplateCompilerBase $compiler) */ public function compileSpecialVariable($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter) { - $tag = strtolower(trim($parameter[ 0 ], '"\'')); + $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 ]) ? strtolower($compiler->getId($parameter[ 2 ])) : 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 d53ef51ff..590cba5af 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 = strtolower($compiler->getId($_index[ 0 ])); + $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,7 +40,7 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $ case 'foreach': case 'section': if (!isset(Smarty_Internal_TemplateCompilerBase::$_tag_objects[ $variable ])) { - $class = 'Smarty_Internal_Compile_' . ucfirst($variable); + $class = 'Smarty_Internal_Compile_' . smarty_ucfirst_ascii($variable); Smarty_Internal_TemplateCompilerBase::$_tag_objects[ $variable ] = new $class; } return Smarty_Internal_TemplateCompilerBase::$_tag_objects[ $variable ]->compileSpecialVariable( @@ -76,7 +76,7 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $ $compiler->trigger_template_error("(secure mode) super globals not permitted"); break; } - $compiled_ref = '$_' . strtoupper($variable); + $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 b07615526..634ad8315 100644 --- a/libs/sysplugins/smarty_internal_extension_handler.php +++ b/libs/sysplugins/smarty_internal_extension_handler.php @@ -88,20 +88,19 @@ public function _callExternalMethod(Smarty_Internal_Data $data, $name, $args) $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 ] = strtolower( - join( - '_', - preg_split( - '/([A-Z][^A-Z]*)/', - $basename, - -1, - PREG_SPLIT_NO_EMPTY | - PREG_SPLIT_DELIM_CAPTURE - ) + $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; @@ -145,7 +144,7 @@ public function _callExternalMethod(Smarty_Internal_Data $data, $name, $args) public function upperCase($name) { $_name = explode('_', $name); - $_name = array_map('ucfirst', $_name); + $_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 3bd659cb8..6ddcaec94 100644 --- a/libs/sysplugins/smarty_internal_method_loadplugin.php +++ b/libs/sysplugins/smarty_internal_method_loadplugin.php @@ -40,7 +40,7 @@ public function loadPlugin(Smarty $smarty, $plugin_name, $check) throw new SmartyException("plugin {$plugin_name} is not a valid name format"); } if (!empty($match[ 2 ])) { - $file = SMARTY_SYSPLUGINS_DIR . strtolower($plugin_name) . '.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 @@ public function loadPlugin(Smarty $smarty, $plugin_name, $check) } // plugin filename is expected to be: [type].[name].php $_plugin_filename = "{$match[1]}.{$match[4]}.php"; - $_lower_filename = strtolower($_plugin_filename); + $_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 d6f86ac0a..545c1e4ff 100644 --- a/libs/sysplugins/smarty_internal_templatecompilerbase.php +++ b/libs/sysplugins/smarty_internal_templatecompilerbase.php @@ -605,7 +605,7 @@ public function compilePHPFunctionCall($name, $parameter) if (strcasecmp($name, 'isset') === 0 || strcasecmp($name, 'empty') === 0 || strcasecmp($name, 'array') === 0 || is_callable($name) ) { - $func_name = strtolower($name); + $func_name = smarty_strtolower_ascii($name); if ($func_name === 'isset') { if (count($parameter) === 0) { @@ -765,7 +765,7 @@ public function getTagCompiler($tag) if (!isset(self::$_tag_objects[ $tag ])) { // lazy load internal compiler plugin $_tag = explode('_', $tag); - $_tag = array_map('ucfirst', $_tag); + $_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 7fe84536f..3c43a9f46 100644 --- a/libs/sysplugins/smarty_resource.php +++ b/libs/sysplugins/smarty_resource.php @@ -76,11 +76,11 @@ public static function load(Smarty $smarty, $type) } // try sysplugins dir if (isset(self::$sysplugins[ $type ])) { - $_resource_class = 'Smarty_Internal_Resource_' . ucfirst($type); + $_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_' . ucfirst($type); + $_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();