diff --git a/lib/smarty/libs/Autoloader.php b/lib/smarty/libs/Autoloader.php index 1673ce2f..da7e32ab 100644 --- a/lib/smarty/libs/Autoloader.php +++ b/lib/smarty/libs/Autoloader.php @@ -5,6 +5,11 @@ * @package Smarty */ + +if (!defined('SMARTY_HELPER_FUNCTIONS_LOADED')) { + include __DIR__ . '/functions.php'; +} + /** * Smarty Autoloader * @@ -73,7 +78,7 @@ class Smarty_Autoloader */ public static function register($prepend = false) { - self::$SMARTY_DIR = defined('SMARTY_DIR') ? SMARTY_DIR : dirname(__FILE__) . DIRECTORY_SEPARATOR; + self::$SMARTY_DIR = defined('SMARTY_DIR') ? SMARTY_DIR : __DIR__ . DIRECTORY_SEPARATOR; self::$SMARTY_SYSPLUGINS_DIR = defined('SMARTY_SYSPLUGINS_DIR') ? SMARTY_SYSPLUGINS_DIR : self::$SMARTY_DIR . 'sysplugins' . DIRECTORY_SEPARATOR; spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend); @@ -89,7 +94,7 @@ class Smarty_Autoloader 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/lib/smarty/libs/Smarty.class.php b/lib/smarty/libs/Smarty.class.php index 820a1ebd..5d2e3a4b 100644 --- a/lib/smarty/libs/Smarty.class.php +++ b/lib/smarty/libs/Smarty.class.php @@ -36,7 +36,7 @@ if (!defined('SMARTY_DIR')) { /** * */ - define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR); + define('SMARTY_DIR', __DIR__ . DIRECTORY_SEPARATOR); } /** * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins. @@ -60,12 +60,21 @@ if (!defined('SMARTY_MBSTRING')) { */ define('SMARTY_MBSTRING', function_exists('mb_get_info')); } + +/** + * Load helper functions + */ +if (!defined('SMARTY_HELPER_FUNCTIONS_LOADED')) { + include __DIR__ . '/functions.php'; +} + /** * Load Smarty_Autoloader */ if (!class_exists('Smarty_Autoloader')) { - include dirname(__FILE__) . '/bootstrap.php'; + include __DIR__ . '/bootstrap.php'; } + /** * Load always needed external class files */ @@ -98,7 +107,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '4.1.1'; + const SMARTY_VERSION = '4.3.0'; /** * define variable scopes */ diff --git a/lib/smarty/libs/bootstrap.php b/lib/smarty/libs/bootstrap.php index 2c830468..a226ac04 100644 --- a/lib/smarty/libs/bootstrap.php +++ b/lib/smarty/libs/bootstrap.php @@ -11,6 +11,6 @@ * Load and register Smarty Autoloader */ if (!class_exists('Smarty_Autoloader')) { - include dirname(__FILE__) . '/Autoloader.php'; + include __DIR__ . '/Autoloader.php'; } Smarty_Autoloader::register(true); diff --git a/lib/smarty/libs/debug.tpl b/lib/smarty/libs/debug.tpl index edc7bef9..4f82a582 100644 --- a/lib/smarty/libs/debug.tpl +++ b/lib/smarty/libs/debug.tpl @@ -1,9 +1,9 @@ {capture name='_smarty_debug' assign=debug_output} - - + + Smarty Debug Console - @@ -112,11 +115,11 @@

included templates & config files (load time in seconds)

{foreach $template_data as $template} - {$template.name} -
   + {$template.name} +
   (compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"}) -
+
{/foreach}
{/if} @@ -125,13 +128,22 @@ {foreach $assigned_vars as $vars} - - + + + - - {/foreach}

${$vars@key}

- {if isset($vars['nocache'])}Nocache
{/if} - {if isset($vars['scope'])}Origin: {$vars['scope']|debug_print_var nofilter}{/if} +
+

${$vars@key}

+ {if isset($vars['nocache'])}Nocache
{/if} + {if isset($vars['scope'])}Origin: {$vars['scope']|debug_print_var nofilter}{/if} +
+

Value

+ {$vars['value']|debug_print_var:10:80 nofilter} +
+ {if isset($vars['attributes'])} +

Attributes

+ {$vars['attributes']|debug_print_var nofilter} + {/if}

Value

{$vars['value']|debug_print_var:10:80 nofilter}
{if isset($vars['attributes'])}

Attributes

{$vars['attributes']|debug_print_var nofilter} {/if}
@@ -139,11 +151,14 @@ {foreach $config_vars as $vars} - - + + - {/foreach} diff --git a/lib/smarty/libs/functions.php b/lib/smarty/libs/functions.php new file mode 100644 index 00000000..bac00e52 --- /dev/null +++ b/lib/smarty/libs/functions.php @@ -0,0 +1,51 @@ + $_value) { switch ($_key) { case 'time': - if (!is_array($_value) && $_value !== null) { - $template->_checkPlugins( - array( - array( - 'function' => 'smarty_make_timestamp', - 'file' => SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php' - ) - ) - ); - $time = smarty_make_timestamp($_value); - } + $$_key = $_value; // we'll handle conversion below break; case 'month_names': if (is_array($_value) && count($_value) === 12) { @@ -178,43 +169,59 @@ function smarty_function_html_select_date($params, Smarty_Internal_Template $tem } // Note: date() is faster than strftime() // Note: explode(date()) is faster than date() date() date() - if (isset($params[ 'time' ]) && is_array($params[ 'time' ])) { - if (isset($params[ 'time' ][ $prefix . 'Year' ])) { + + if (isset($time) && is_array($time)) { + if (isset($time[$prefix . 'Year'])) { // $_REQUEST[$field_array] given - foreach (array( - 'Y' => 'Year', - 'm' => 'Month', - 'd' => 'Day' - ) as $_elementKey => $_elementName) { + foreach ([ + 'Y' => 'Year', + 'm' => 'Month', + 'd' => 'Day' + ] as $_elementKey => $_elementName) { $_variableName = '_' . strtolower($_elementName); $$_variableName = - isset($params[ 'time' ][ $prefix . $_elementName ]) ? $params[ 'time' ][ $prefix . $_elementName ] : + isset($time[$prefix . $_elementName]) ? $time[$prefix . $_elementName] : date($_elementKey); } - } elseif (isset($params[ 'time' ][ $field_array ][ $prefix . 'Year' ])) { + } elseif (isset($time[$field_array][$prefix . 'Year'])) { // $_REQUEST given - foreach (array( - 'Y' => 'Year', - 'm' => 'Month', - 'd' => 'Day' - ) as $_elementKey => $_elementName) { + foreach ([ + 'Y' => 'Year', + 'm' => 'Month', + 'd' => 'Day' + ] as $_elementKey => $_elementName) { $_variableName = '_' . strtolower($_elementName); - $$_variableName = isset($params[ 'time' ][ $field_array ][ $prefix . $_elementName ]) ? - $params[ 'time' ][ $field_array ][ $prefix . $_elementName ] : date($_elementKey); + $$_variableName = isset($time[$field_array][$prefix . $_elementName]) ? + $time[$field_array][$prefix . $_elementName] : date($_elementKey); } } else { // no date found, use NOW - list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d')); + [$_year, $_month, $_day] = explode('-', date('Y-m-d')); } + } elseif (isset($time) && preg_match("/(\d*)-(\d*)-(\d*)/", $time, $matches)) { + $_year = $_month = $_day = null; + if ($matches[1] > '') $_year = (int) $matches[1]; + if ($matches[2] > '') $_month = (int) $matches[2]; + if ($matches[3] > '') $_day = (int) $matches[3]; } elseif ($time === null) { if (array_key_exists('time', $params)) { - $_year = $_month = $_day = $time = null; + $_year = $_month = $_day = null; } else { - list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d')); + [$_year, $_month, $_day] = explode('-', date('Y-m-d')); } } else { - list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d', $time)); + $template->_checkPlugins( + array( + array( + 'function' => 'smarty_make_timestamp', + 'file' => SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php' + ) + ) + ); + $time = smarty_make_timestamp($time); + [$_year, $_month, $_day] = explode('-', date('Y-m-d', $time)); } + // make syntax "+N" or "-N" work with $start_year and $end_year // Note preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match) is slower than trim+substr foreach (array( @@ -309,8 +316,8 @@ function smarty_function_html_select_date($params, Smarty_Internal_Template $tem for ($i = 1; $i <= 12; $i++) { $_val = sprintf('%02d', $i); $_text = isset($month_names) ? smarty_function_escape_special_chars($month_names[ $i ]) : - ($month_format === '%m' ? $_val : strftime($month_format, $_month_timestamps[ $i ])); - $_value = $month_value_format === '%m' ? $_val : strftime($month_value_format, $_month_timestamps[ $i ]); + ($month_format === '%m' ? $_val : @strftime($month_format, $_month_timestamps[ $i ])); + $_value = $month_value_format === '%m' ? $_val : @strftime($month_value_format, $_month_timestamps[ $i ]); $_html_months .= '' . $option_separator; } diff --git a/lib/smarty/libs/plugins/function.mailto.php b/lib/smarty/libs/plugins/function.mailto.php index 834d0535..671ac069 100644 --- a/lib/smarty/libs/plugins/function.mailto.php +++ b/lib/smarty/libs/plugins/function.mailto.php @@ -48,8 +48,13 @@ */ function smarty_function_mailto($params) { - static $_allowed_encoding = - array('javascript' => true, 'javascript_charcode' => true, 'hex' => true, 'none' => true); + static $_allowed_encoding = [ + 'javascript' => true, + 'javascript_charcode' => true, + 'hex' => true, + 'none' => true + ]; + $extra = ''; if (empty($params[ 'address' ])) { trigger_error("mailto: missing 'address' parameter", E_USER_WARNING); @@ -57,19 +62,19 @@ function smarty_function_mailto($params) } else { $address = $params[ 'address' ]; } + $text = $address; + // netscape and mozilla do not decode %40 (@) in BCC field (bug?) // so, don't encode it. - $search = array('%40', '%2C'); - $replace = array('@', ','); - $mail_parms = array(); + $mail_parms = []; foreach ($params as $var => $value) { switch ($var) { case 'cc': case 'bcc': case 'followupto': if (!empty($value)) { - $mail_parms[] = $var . '=' . str_replace($search, $replace, rawurlencode($value)); + $mail_parms[] = $var . '=' . str_replace(['%40', '%2C'], ['@', ','], rawurlencode($value)); } break; case 'subject': @@ -83,6 +88,7 @@ function smarty_function_mailto($params) default: } } + if ($mail_parms) { $address .= '?' . join('&', $mail_parms); } @@ -94,19 +100,21 @@ function smarty_function_mailto($params) ); return; } + + $string = '' . htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, Smarty::$_CHARSET) . ''; + if ($encode === 'javascript') { - $string = '' . $text . ''; $js_encode = ''; for ($x = 0, $_length = strlen($string); $x < $_length; $x++) { $js_encode .= '%' . bin2hex($string[ $x ]); } return ''; } elseif ($encode === 'javascript_charcode') { - $string = '' . $text . ''; for ($x = 0, $_length = strlen($string); $x < $_length; $x++) { $ord[] = ord($string[ $x ]); } - return ''; + return ''; } elseif ($encode === 'hex') { preg_match('!^(.*)(\?.*)$!', $address, $match); if (!empty($match[ 2 ])) { @@ -129,6 +137,6 @@ function smarty_function_mailto($params) return '' . $text_encode . ''; } else { // no encoding - return '' . $text . ''; + return $string; } } diff --git a/lib/smarty/libs/plugins/function.math.php b/lib/smarty/libs/plugins/function.math.php index 8560e944..f9cf67fe 100644 --- a/lib/smarty/libs/plugins/function.math.php +++ b/lib/smarty/libs/plugins/function.math.php @@ -70,7 +70,7 @@ function smarty_function_math($params, $template) $number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number $functionsOrVars = '((?:0x[a-fA-F0-9]+)|([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*))'; $operators = '[,+\/*\^%-]'; // Allowed math operators - $regexp = '/^(('.$number.'|'.$functionsOrVars.'|('.$functionsOrVars.'\s*\((?1)+\)|\((?1)+\)))(?:'.$operators.'(?1))?)+$/'; + $regexp = '/^(('.$number.'|'.$functionsOrVars.'|('.$functionsOrVars.'\s*\((?1)*\)|\((?1)*\)))(?:'.$operators.'(?1))?)+$/'; if (!preg_match($regexp, $equation)) { trigger_error("math: illegal characters", E_USER_WARNING); diff --git a/lib/smarty/libs/plugins/modifier.capitalize.php b/lib/smarty/libs/plugins/modifier.capitalize.php index c5fc400a..2903d61d 100644 --- a/lib/smarty/libs/plugins/modifier.capitalize.php +++ b/lib/smarty/libs/plugins/modifier.capitalize.php @@ -22,6 +22,8 @@ */ function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = false) { + $string = (string) $string; + if (Smarty::$_MBSTRING) { if ($lc_rest) { // uppercase (including hyphenated words) diff --git a/lib/smarty/libs/plugins/modifier.count.php b/lib/smarty/libs/plugins/modifier.count.php new file mode 100644 index 00000000..ca35fc11 --- /dev/null +++ b/lib/smarty/libs/plugins/modifier.count.php @@ -0,0 +1,36 @@ + Prior to PHP 8.0.0, if the parameter was neither an array nor an object that implements the Countable interface, + * > 1 would be returned, unless value was null, in which case 0 would be returned. + */ + + if ($arrayOrObject instanceof Countable || is_array($arrayOrObject)) { + return count($arrayOrObject, (int) $mode); + } elseif ($arrayOrObject === null) { + return 0; + } + return 1; +} diff --git a/lib/smarty/libs/plugins/modifier.date_format.php b/lib/smarty/libs/plugins/modifier.date_format.php index 8e7e0b6e..e3589fd0 100644 --- a/lib/smarty/libs/plugins/modifier.date_format.php +++ b/lib/smarty/libs/plugins/modifier.date_format.php @@ -78,7 +78,8 @@ function smarty_modifier_date_format($string, $format = null, $default_date = '' } $format = str_replace($_win_from, $_win_to, $format); } - return strftime($format, $timestamp); + // @ to suppress deprecation errors when running in PHP8.1 or higher. + return @strftime($format, $timestamp); } else { return date($format, $timestamp); } diff --git a/lib/smarty/libs/plugins/modifier.escape.php b/lib/smarty/libs/plugins/modifier.escape.php index 3ce48382..11e44682 100644 --- a/lib/smarty/libs/plugins/modifier.escape.php +++ b/lib/smarty/libs/plugins/modifier.escape.php @@ -23,7 +23,6 @@ */ function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $double_encode = true) { - static $_double_encode = true; static $is_loaded_1 = false; static $is_loaded_2 = false; if (!$char_set) { @@ -34,87 +33,15 @@ function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $ switch ($esc_type) { case 'html': - if ($_double_encode) { - // php >=5.3.2 - go native - return htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode); - } else { - if ($double_encode) { - // php <5.2.3 - only handle double encoding - return htmlspecialchars($string, ENT_QUOTES, $char_set); - } else { - // php <5.2.3 - prevent double encoding - $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); - $string = htmlspecialchars($string, ENT_QUOTES, $char_set); - $string = str_replace( - array( - '%%%SMARTY_START%%%', - '%%%SMARTY_END%%%' - ), - array( - '&', - ';' - ), - $string - ); - return $string; - } - } + return htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode); // no break case 'htmlall': if (Smarty::$_MBSTRING) { - // mb_convert_encoding ignores htmlspecialchars() - if ($_double_encode) { - // php >=5.3.2 - go native - $string = htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode); - } else { - if ($double_encode) { - // php <5.2.3 - only handle double encoding - $string = htmlspecialchars($string, ENT_QUOTES, $char_set); - } else { - // php <5.2.3 - prevent double encoding - $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); - $string = htmlspecialchars($string, ENT_QUOTES, $char_set); - $string = - str_replace( - array( - '%%%SMARTY_START%%%', - '%%%SMARTY_END%%%' - ), - array( - '&', - ';' - ), - $string - ); - return $string; - } - } - // htmlentities() won't convert everything, so use mb_convert_encoding - return mb_convert_encoding($string, 'HTML-ENTITIES', $char_set); + $string = mb_convert_encoding($string, 'UTF-8', $char_set); + return htmlentities($string, ENT_QUOTES, 'UTF-8', $double_encode); } // no MBString fallback - if ($_double_encode) { - return htmlentities($string, ENT_QUOTES, $char_set, $double_encode); - } else { - if ($double_encode) { - return htmlentities($string, ENT_QUOTES, $char_set); - } else { - $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); - $string = htmlentities($string, ENT_QUOTES, $char_set); - $string = str_replace( - array( - '%%%SMARTY_START%%%', - '%%%SMARTY_END%%%' - ), - array( - '&', - ';' - ), - $string - ); - return $string; - } - } + return htmlentities($string, ENT_QUOTES, $char_set, $double_encode); // no break case 'url': return rawurlencode($string); diff --git a/lib/smarty/libs/plugins/modifier.explode.php b/lib/smarty/libs/plugins/modifier.explode.php new file mode 100644 index 00000000..5186fde3 --- /dev/null +++ b/lib/smarty/libs/plugins/modifier.explode.php @@ -0,0 +1,25 @@ +=8.1 + return explode($separator, $string ?? '', $limit ?? PHP_INT_MAX); +} diff --git a/lib/smarty/libs/plugins/modifier.number_format.php b/lib/smarty/libs/plugins/modifier.number_format.php new file mode 100644 index 00000000..8c612601 --- /dev/null +++ b/lib/smarty/libs/plugins/modifier.number_format.php @@ -0,0 +1,26 @@ +=8.1 + return number_format($num ?? 0.0, $decimals, $decimal_separator, $thousands_separator); +} diff --git a/lib/smarty/libs/plugins/modifiercompiler.escape.php b/lib/smarty/libs/plugins/modifiercompiler.escape.php index 1fc5e781..602c3dbf 100644 --- a/lib/smarty/libs/plugins/modifiercompiler.escape.php +++ b/lib/smarty/libs/plugins/modifiercompiler.escape.php @@ -18,12 +18,10 @@ * @param Smarty_Internal_TemplateCompilerBase $compiler * * @return string with compiled code - * @throws \SmartyException + * @throws SmartyException */ function smarty_modifiercompiler_escape($params, Smarty_Internal_TemplateCompilerBase $compiler) { - static $_double_encode = true; - static $is_loaded = false; $compiler->template->_checkPlugins( array( array( @@ -41,41 +39,18 @@ function smarty_modifiercompiler_escape($params, Smarty_Internal_TemplateCompile } switch ($esc_type) { case 'html': - if ($_double_encode) { - return 'htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' . - var_export($double_encode, true) . ')'; - } elseif ($double_encode) { - return 'htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')'; - } else { - // fall back to modifier.escape.php - } + return 'htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' . + var_export($double_encode, true) . ')'; // no break case 'htmlall': if (Smarty::$_MBSTRING) { - if ($_double_encode) { - // php >=5.2.3 - go native - return 'mb_convert_encoding(htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . - var_export($char_set, true) . ', ' . var_export($double_encode, true) . - '), "HTML-ENTITIES", ' . var_export($char_set, true) . ')'; - } elseif ($double_encode) { - // php <5.2.3 - only handle double encoding - return 'mb_convert_encoding(htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . - var_export($char_set, true) . '), "HTML-ENTITIES", ' . var_export($char_set, true) . ')'; - } else { - // fall back to modifier.escape.php - } + return 'htmlentities(mb_convert_encoding((string)' . $params[ 0 ] . ', \'UTF-8\', ' . + var_export($char_set, true) . '), ENT_QUOTES, \'UTF-8\', ' . + var_export($double_encode, true) . ')'; } // no MBString fallback - if ($_double_encode) { - // php >=5.2.3 - go native - return 'htmlentities((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' . - var_export($double_encode, true) . ')'; - } elseif ($double_encode) { - // php <5.2.3 - only handle double encoding - return 'htmlentities((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')'; - } else { - // fall back to modifier.escape.php - } + return 'htmlentities((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' . + var_export($double_encode, true) . ')'; // no break case 'url': return 'rawurlencode((string)' . $params[ 0 ] . ')'; diff --git a/lib/smarty/libs/plugins/modifiercompiler.nl2br.php b/lib/smarty/libs/plugins/modifiercompiler.nl2br.php new file mode 100644 index 00000000..308c00e4 --- /dev/null +++ b/lib/smarty/libs/plugins/modifiercompiler.nl2br.php @@ -0,0 +1,23 @@ +]*?>!', ' ', {$params[0]})"; + return "preg_replace('!<[^>]*?>!', ' ', {$params[0]} ?: '')"; } else { - return 'strip_tags(' . $params[ 0 ] . ')'; + return 'strip_tags((string) ' . $params[ 0 ] . ')'; } } diff --git a/lib/smarty/libs/plugins/modifiercompiler.strlen.php b/lib/smarty/libs/plugins/modifiercompiler.strlen.php new file mode 100644 index 00000000..d43e8ef1 --- /dev/null +++ b/lib/smarty/libs/plugins/modifiercompiler.strlen.php @@ -0,0 +1,23 @@ +template->_checkPlugins( + array( + array( + 'function' => 'smarty_literal_compiler_param', + 'file' => SMARTY_PLUGINS_DIR . 'shared.literal_compiler_param.php' + ) + ) + ); + + $esc_type = smarty_literal_compiler_param($params, 1, 'html'); + if (!isset($params[ 2 ])) { $params[ 2 ] = '\'' . addslashes(Smarty::$_CHARSET) . '\''; - } else { - $params[ 2 ] = "'{$params[ 2 ]}'"; } - switch (trim($params[ 1 ], '"\'')) { + + switch ($esc_type) { case 'entity': case 'htmlall': if (Smarty::$_MBSTRING) { - return 'mb_convert_encoding(' . $params[ 0 ] . ', ' . $params[ 2 ] . ', \'HTML-ENTITIES\')'; + return 'html_entity_decode(mb_convert_encoding(' . $params[ 0 ] . ', ' . $params[ 2 ] . ', \'UTF-8\'), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, ' . $params[ 2 ] . ')'; } - return 'html_entity_decode(' . $params[ 0 ] . ', ENT_NOQUOTES, ' . $params[ 2 ] . ')'; + return 'html_entity_decode(' . $params[ 0 ] . ', ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, ' . $params[ 2 ] . ')'; case 'html': return 'htmlspecialchars_decode(' . $params[ 0 ] . ', ENT_QUOTES)'; case 'url': diff --git a/lib/smarty/libs/plugins/modifiercompiler.upper.php b/lib/smarty/libs/plugins/modifiercompiler.upper.php index e12ae676..31a90a05 100644 --- a/lib/smarty/libs/plugins/modifiercompiler.upper.php +++ b/lib/smarty/libs/plugins/modifiercompiler.upper.php @@ -21,8 +21,8 @@ function smarty_modifiercompiler_upper($params) { if (Smarty::$_MBSTRING) { - return 'mb_strtoupper(' . $params[ 0 ] . ', \'' . addslashes(Smarty::$_CHARSET) . '\')'; + return 'mb_strtoupper(' . $params[ 0 ] . ' ?? \'\', \'' . addslashes(Smarty::$_CHARSET) . '\')'; } // no MBString fallback - return 'strtoupper(' . $params[ 0 ] . ')'; + return 'strtoupper(' . $params[ 0 ] . ' ?? \'\')'; } diff --git a/lib/smarty/libs/plugins/shared.mb_str_replace.php b/lib/smarty/libs/plugins/shared.mb_str_replace.php index 226d9035..7e85f7aa 100644 --- a/lib/smarty/libs/plugins/shared.mb_str_replace.php +++ b/lib/smarty/libs/plugins/shared.mb_str_replace.php @@ -44,9 +44,43 @@ if (!function_exists('smarty_mb_str_replace')) { } } } else { - $parts = mb_split(preg_quote($search), $subject) ?: array(); + $mb_reg_charset = mb_regex_encoding(); + // Check if mbstring regex is using UTF-8 + $reg_is_unicode = !strcasecmp($mb_reg_charset, "UTF-8"); + if(!$reg_is_unicode) { + // ...and set to UTF-8 if not + mb_regex_encoding("UTF-8"); + } + + // See if charset used by Smarty is matching one used by regex... + $current_charset = mb_regex_encoding(); + $convert_result = (bool)strcasecmp(Smarty::$_CHARSET, $current_charset); + if($convert_result) { + // ...convert to it if not. + $subject = mb_convert_encoding($subject, $current_charset, Smarty::$_CHARSET); + $search = mb_convert_encoding($search, $current_charset, Smarty::$_CHARSET); + $replace = mb_convert_encoding($replace, $current_charset, Smarty::$_CHARSET); + } + + $parts = mb_split(preg_quote($search), $subject ?? "") ?: array(); + // If original regex encoding was not unicode... + if(!$reg_is_unicode) { + // ...restore original regex encoding to avoid breaking the system. + mb_regex_encoding($mb_reg_charset); + } + if($parts === false) { + // This exception is thrown if call to mb_split failed. + // Usually it happens, when $search or $replace are not valid for given mb_regex_encoding(). + // There may be other cases for it to fail, please file an issue if you find a reproducible one. + throw new SmartyException("Source string is not a valid $current_charset sequence (probably)"); + } + $count = count($parts) - 1; $subject = implode($replace, $parts); + // Convert results back to charset used by Smarty, if needed. + if($convert_result) { + $subject = mb_convert_encoding($subject, Smarty::$_CHARSET, $current_charset); + } } return $subject; } diff --git a/lib/smarty/libs/sysplugins/smarty_cacheresource.php b/lib/smarty/libs/sysplugins/smarty_cacheresource.php index 91e9f392..db68f9bf 100644 --- a/lib/smarty/libs/sysplugins/smarty_cacheresource.php +++ b/lib/smarty/libs/sysplugins/smarty_cacheresource.php @@ -205,11 +205,11 @@ abstract class Smarty_CacheResource } // try sysplugins dir if (isset(self::$sysplugins[ $type ])) { - $cache_resource_class = 'Smarty_Internal_CacheResource_' . ucfirst($type); + $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_' . 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/lib/smarty/libs/sysplugins/smarty_cacheresource_keyvaluestore.php b/lib/smarty/libs/sysplugins/smarty_cacheresource_keyvaluestore.php index 59bf1d4a..4b1c0f6d 100644 --- a/lib/smarty/libs/sysplugins/smarty_cacheresource_keyvaluestore.php +++ b/lib/smarty/libs/sysplugins/smarty_cacheresource_keyvaluestore.php @@ -244,7 +244,7 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource */ protected function sanitize($string) { - $string = trim($string, '|'); + $string = trim((string)$string, '|'); if (!$string) { return ''; } @@ -428,7 +428,7 @@ abstract class Smarty_CacheResource_KeyValueStore extends Smarty_CacheResource $t[] = 'IVK#COMPILE' . $_compile; } $_name .= '#'; - $cid = trim($cache_id, '|'); + $cid = trim((string)$cache_id, '|'); if (!$cid) { return $t; } diff --git a/lib/smarty/libs/sysplugins/smarty_internal_compile_private_foreachsection.php b/lib/smarty/libs/sysplugins/smarty_internal_compile_private_foreachsection.php index d3aab24b..246350dc 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_compile_private_foreachsection.php +++ b/lib/smarty/libs/sysplugins/smarty_internal_compile_private_foreachsection.php @@ -143,7 +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)) { - $this->matchResults[ $key ][ strtolower($m) ] = true; + $this->matchResults[ $key ][ smarty_strtolower_ascii($m) ] = true; } } } @@ -213,12 +213,12 @@ class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_Com */ 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/lib/smarty/libs/sysplugins/smarty_internal_compile_private_modifier.php b/lib/smarty/libs/sysplugins/smarty_internal_compile_private_modifier.php index 72773fff..aea082f0 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_compile_private_modifier.php +++ b/lib/smarty/libs/sysplugins/smarty_internal_compile_private_modifier.php @@ -109,6 +109,9 @@ class Smarty_Internal_Compile_Private_Modifier extends Smarty_Internal_CompileBa if (!is_object($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedPhpModifier($modifier, $compiler) ) { + trigger_error('Using php-function "' . $modifier . '" as a modifier is deprecated and will be ' . + 'removed in a future release. Use Smarty::registerPlugin to explicitly register ' . + 'a custom modifier.', E_USER_DEPRECATED); $output = "{$modifier}({$params})"; } $compiler->known_modifier_type[ $modifier ] = $type; diff --git a/lib/smarty/libs/sysplugins/smarty_internal_compile_private_print_expression.php b/lib/smarty/libs/sysplugins/smarty_internal_compile_private_print_expression.php index 23cae8ae..96bd3724 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_compile_private_print_expression.php +++ b/lib/smarty/libs/sysplugins/smarty_internal_compile_private_print_expression.php @@ -93,7 +93,7 @@ class Smarty_Internal_Compile_Private_Print_Expression extends Smarty_Internal_C } // autoescape html if ($compiler->template->smarty->escape_html) { - $output = "htmlspecialchars({$output}, ENT_QUOTES, '" . addslashes(Smarty::$_CHARSET) . "')"; + $output = "htmlspecialchars((string) {$output}, ENT_QUOTES, '" . addslashes(Smarty::$_CHARSET) . "')"; } // loop over registered filters if (!empty($compiler->template->smarty->registered_filters[ Smarty::FILTER_VARIABLE ])) { diff --git a/lib/smarty/libs/sysplugins/smarty_internal_compile_private_special_variable.php b/lib/smarty/libs/sysplugins/smarty_internal_compile_private_special_variable.php index d53ef51f..590cba5a 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_compile_private_special_variable.php +++ b/lib/smarty/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 @@ class Smarty_Internal_Compile_Private_Special_Variable extends Smarty_Internal_C 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 @@ class Smarty_Internal_Compile_Private_Special_Variable extends Smarty_Internal_C $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/lib/smarty/libs/sysplugins/smarty_internal_debug.php b/lib/smarty/libs/sysplugins/smarty_internal_debug.php index 24b233e2..570819d2 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_debug.php +++ b/lib/smarty/libs/sysplugins/smarty_internal_debug.php @@ -210,7 +210,7 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data // copy the working dirs from application $debObj->setCompileDir($smarty->getCompileDir()); // init properties by hand as user may have edited the original Smarty class - $debObj->setPluginsDir(is_dir(dirname(__FILE__) . '/../plugins') ? dirname(__FILE__) . + $debObj->setPluginsDir(is_dir(__DIR__ . '/../plugins') ? __DIR__ . '/../plugins' : $smarty->getPluginsDir()); $debObj->force_compile = false; $debObj->compile_check = Smarty::COMPILECHECK_ON; @@ -221,7 +221,7 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data $debObj->debugging_ctrl = 'NONE'; $debObj->error_reporting = E_ALL & ~E_NOTICE; $debObj->debug_tpl = - isset($smarty->debug_tpl) ? $smarty->debug_tpl : 'file:' . dirname(__FILE__) . '/../debug.tpl'; + isset($smarty->debug_tpl) ? $smarty->debug_tpl : 'file:' . __DIR__ . '/../debug.tpl'; $debObj->registered_plugins = array(); $debObj->registered_resources = array(); $debObj->registered_filters = array(); diff --git a/lib/smarty/libs/sysplugins/smarty_internal_extension_handler.php b/lib/smarty/libs/sysplugins/smarty_internal_extension_handler.php index b0761552..3ef040ab 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_extension_handler.php +++ b/lib/smarty/libs/sysplugins/smarty_internal_extension_handler.php @@ -36,6 +36,7 @@ * @property Smarty_Internal_Method_RegisterPlugin $registerPlugin * @property mixed|\Smarty_Template_Cached configLoad */ +#[\AllowDynamicProperties] class Smarty_Internal_Extension_Handler { public $objType = null; @@ -88,20 +89,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 ] = 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 +145,7 @@ class Smarty_Internal_Extension_Handler 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/lib/smarty/libs/sysplugins/smarty_internal_method_loadplugin.php b/lib/smarty/libs/sysplugins/smarty_internal_method_loadplugin.php index 3bd659cb..6ddcaec9 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_method_loadplugin.php +++ b/lib/smarty/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 . 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 @@ class Smarty_Internal_Method_LoadPlugin } // 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/lib/smarty/libs/sysplugins/smarty_internal_method_mustcompile.php b/lib/smarty/libs/sysplugins/smarty_internal_method_mustcompile.php index 39318838..381346c8 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_method_mustcompile.php +++ b/lib/smarty/libs/sysplugins/smarty_internal_method_mustcompile.php @@ -32,7 +32,7 @@ class Smarty_Internal_Method_MustCompile { if (!$_template->source->exists) { if ($_template->_isSubTpl()) { - $parent_resource = " in '$_template->parent->template_resource}'"; + $parent_resource = " in '{$_template->parent->template_resource}'"; } else { $parent_resource = ''; } diff --git a/lib/smarty/libs/sysplugins/smarty_internal_runtime_make_nocache.php b/lib/smarty/libs/sysplugins/smarty_internal_runtime_make_nocache.php index 53069148..7994aa04 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_runtime_make_nocache.php +++ b/lib/smarty/libs/sysplugins/smarty_internal_runtime_make_nocache.php @@ -22,7 +22,7 @@ class Smarty_Internal_Runtime_Make_Nocache { if (isset($tpl->tpl_vars[ $var ])) { $export = - preg_replace('/^Smarty_Variable::__set_state[(]|[)]$/', '', var_export($tpl->tpl_vars[ $var ], true)); + preg_replace('/^\\\\?Smarty_Variable::__set_state[(]|[)]$/', '', var_export($tpl->tpl_vars[ $var ], true)); if (preg_match('/(\w+)::__set_state/', $export, $match)) { throw new SmartyException("{make_nocache \${$var}} in template '{$tpl->source->name}': variable does contain object '{$match[1]}' not implementing method '__set_state'"); } diff --git a/lib/smarty/libs/sysplugins/smarty_internal_runtime_writefile.php b/lib/smarty/libs/sysplugins/smarty_internal_runtime_writefile.php index 4383e6f3..492d5eb2 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_runtime_writefile.php +++ b/lib/smarty/libs/sysplugins/smarty_internal_runtime_writefile.php @@ -29,12 +29,6 @@ class Smarty_Internal_Runtime_WriteFile { $_error_reporting = error_reporting(); error_reporting($_error_reporting & ~E_NOTICE & ~E_WARNING); - $_file_perms = property_exists($smarty, '_file_perms') ? $smarty->_file_perms : 0644; - $_dir_perms = - property_exists($smarty, '_dir_perms') ? (isset($smarty->_dir_perms) ? $smarty->_dir_perms : 0777) : 0771; - if ($_file_perms !== null) { - $old_umask = umask(0); - } $_dirpath = dirname($_filepath); // if subdirs, create dir structure if ($_dirpath !== '.') { @@ -42,7 +36,7 @@ class Smarty_Internal_Runtime_WriteFile // loop if concurrency problem occurs // see https://bugs.php.net/bug.php?id=35326 while (!is_dir($_dirpath)) { - if (@mkdir($_dirpath, $_dir_perms, true)) { + if (@mkdir($_dirpath, 0777, true)) { break; } clearstatcache(); @@ -89,11 +83,8 @@ class Smarty_Internal_Runtime_WriteFile error_reporting($_error_reporting); throw new SmartyException("unable to write file {$_filepath}"); } - if ($_file_perms !== null) { - // set file permissions - chmod($_filepath, $_file_perms); - umask($old_umask); - } + // set file permissions + @chmod($_filepath, 0666 & ~umask()); error_reporting($_error_reporting); return true; } diff --git a/lib/smarty/libs/sysplugins/smarty_internal_template.php b/lib/smarty/libs/sysplugins/smarty_internal_template.php index bae22a7d..72d1d52e 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_template.php +++ b/lib/smarty/libs/sysplugins/smarty_internal_template.php @@ -24,6 +24,7 @@ * * @method bool mustCompile() */ +#[\AllowDynamicProperties] class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { /** @@ -292,7 +293,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase $smarty = &$this->smarty; $_templateId = $smarty->_getTemplateId($template, $cache_id, $compile_id, $caching, $tpl); // recursive call ? - if (isset($tpl->templateId) ? $tpl->templateId : $tpl->_getTemplateId() !== $_templateId) { + if ((isset($tpl->templateId) ? $tpl->templateId : $tpl->_getTemplateId()) !== $_templateId) { // already in template cache? if (isset(self::$tplObjCache[ $_templateId ])) { // copy data from cached object @@ -358,7 +359,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase } if ($tpl->caching === 9999) { if (!isset($tpl->compiled)) { - $this->loadCompiled(true); + $tpl->loadCompiled(true); } if ($tpl->compiled->has_nocache_code) { $this->cached->hashes[ $tpl->compiled->nocache_hash ] = true; diff --git a/lib/smarty/libs/sysplugins/smarty_internal_templatebase.php b/lib/smarty/libs/sysplugins/smarty_internal_templatebase.php index 2ffb896f..918362e9 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_templatebase.php +++ b/lib/smarty/libs/sysplugins/smarty_internal_templatebase.php @@ -257,7 +257,7 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data error_reporting($_smarty_old_error_level); } return $result; - } catch (Exception $e) { + } catch (Throwable $e) { while (ob_get_level() > $level) { ob_end_clean(); } diff --git a/lib/smarty/libs/sysplugins/smarty_internal_templatecompilerbase.php b/lib/smarty/libs/sysplugins/smarty_internal_templatecompilerbase.php index bd500abe..d5c18d31 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_templatecompilerbase.php +++ b/lib/smarty/libs/sysplugins/smarty_internal_templatecompilerbase.php @@ -422,9 +422,6 @@ abstract class Smarty_Internal_TemplateCompilerBase try { // save template object in compiler class $this->template = $template; - if (property_exists($this->template->smarty, 'plugin_search_order')) { - $this->plugin_search_order = $this->template->smarty->plugin_search_order; - } if ($this->smarty->debugging) { if (!isset($this->smarty->_debug)) { $this->smarty->_debug = new Smarty_Internal_Debug(); @@ -608,7 +605,7 @@ abstract class Smarty_Internal_TemplateCompilerBase 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) { @@ -768,7 +765,7 @@ abstract class Smarty_Internal_TemplateCompilerBase 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)) @@ -1134,8 +1131,12 @@ abstract class Smarty_Internal_TemplateCompilerBase echo ob_get_clean(); flush(); } - $e = new SmartyCompilerException($error_text); - $e->setLine($line); + $e = new SmartyCompilerException( + $error_text, + 0, + $this->template->source->filepath, + $line + ); $e->source = trim(preg_replace('![\t\r\n]+!', ' ', $match[ $line - 1 ])); $e->desc = $args; $e->template = $this->template->source->filepath; diff --git a/lib/smarty/libs/sysplugins/smarty_internal_testinstall.php b/lib/smarty/libs/sysplugins/smarty_internal_testinstall.php index 1fac79b7..c8ffd4cc 100644 --- a/lib/smarty/libs/sysplugins/smarty_internal_testinstall.php +++ b/lib/smarty/libs/sysplugins/smarty_internal_testinstall.php @@ -144,7 +144,7 @@ class Smarty_Internal_TestInstall } // test if all registered plugins_dir are accessible // and if core plugins directory is still registered - $_core_plugins_dir = realpath(dirname(__FILE__) . '/../plugins'); + $_core_plugins_dir = realpath(__DIR__ . '/../plugins'); $_core_plugins_available = false; foreach ($smarty->getPluginsDir() as $plugin_dir) { $_plugin_dir = $plugin_dir; diff --git a/lib/smarty/libs/sysplugins/smarty_resource.php b/lib/smarty/libs/sysplugins/smarty_resource.php index 7fe84536..3c43a9f4 100644 --- a/lib/smarty/libs/sysplugins/smarty_resource.php +++ b/lib/smarty/libs/sysplugins/smarty_resource.php @@ -76,11 +76,11 @@ abstract class Smarty_Resource } // 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(); diff --git a/lib/smarty/libs/sysplugins/smarty_resource_custom.php b/lib/smarty/libs/sysplugins/smarty_resource_custom.php index 8d66be3a..191fa7c9 100644 --- a/lib/smarty/libs/sysplugins/smarty_resource_custom.php +++ b/lib/smarty/libs/sysplugins/smarty_resource_custom.php @@ -47,7 +47,7 @@ abstract class Smarty_Resource_Custom extends Smarty_Resource */ public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { - $source->filepath = $source->type . ':' . substr(preg_replace('/[^A-Za-z0-9.]/', '', $source->name), 0, 25); + $source->filepath = $source->type . ':' . $this->generateSafeName($source->name); $source->uid = sha1($source->type . ':' . $source->name); $mtime = $this->fetchTimestamp($source->name); if ($mtime !== null) { @@ -88,6 +88,17 @@ abstract class Smarty_Resource_Custom extends Smarty_Resource */ public function getBasename(Smarty_Template_Source $source) { - return basename(substr(preg_replace('/[^A-Za-z0-9.]/', '', $source->name), 0, 25)); + return basename($this->generateSafeName($source->name)); + } + + /** + * Removes special characters from $name and limits its length to 127 characters. + * + * @param $name + * + * @return string + */ + private function generateSafeName($name): string { + return substr(preg_replace('/[^A-Za-z0-9._]/', '', (string) $name), 0, 127); } } diff --git a/lib/smarty/libs/sysplugins/smarty_security.php b/lib/smarty/libs/sysplugins/smarty_security.php index 3c29c813..97cd0521 100644 --- a/lib/smarty/libs/sysplugins/smarty_security.php +++ b/lib/smarty/libs/sysplugins/smarty_security.php @@ -19,6 +19,7 @@ /** * This class does contain the security settings */ +#[\AllowDynamicProperties] class Smarty_Security { @@ -105,7 +106,7 @@ class Smarty_Security * * @var array */ - public $php_modifiers = array('escape', 'count', 'nl2br',); + public $php_modifiers = array('escape', 'count', 'sizeof', 'nl2br',); /** * This is an array of allowed tags. @@ -328,7 +329,7 @@ class Smarty_Security * * @param string $modifier_name * @param object $compiler compiler object - * + * @deprecated * @return boolean true if modifier is trusted */ public function isTrustedPhpModifier($modifier_name, $compiler) @@ -555,35 +556,6 @@ class Smarty_Security throw new SmartyException("URI '{$uri}' not allowed by security setting"); } - /** - * Check if directory of file resource is trusted. - * - * @param string $filepath - * - * @return boolean true if directory is trusted - * @throws SmartyException if PHP directory is not trusted - */ - public function isTrustedPHPDir($filepath) - { - if (empty($this->trusted_dir)) { - throw new SmartyException("directory '{$filepath}' not allowed by security setting (no trusted_dir specified)"); - } - // check if index is outdated - if (!$this->_trusted_dir || $this->_trusted_dir !== $this->trusted_dir) { - $this->_php_resource_dir = array(); - $this->_trusted_dir = $this->trusted_dir; - foreach ((array)$this->trusted_dir as $directory) { - $directory = $this->smarty->_realpath($directory . '/', true); - $this->_php_resource_dir[ $directory ] = true; - } - } - $addPath = $this->_checkDir($filepath, $this->_php_resource_dir); - if ($addPath !== false) { - $this->_php_resource_dir = array_merge($this->_php_resource_dir, $addPath); - } - return true; - } - /** * Remove old directories and its sub folders, add new directories * diff --git a/lib/smarty/libs/sysplugins/smarty_variable.php b/lib/smarty/libs/sysplugins/smarty_variable.php index 914d99bd..6a534228 100644 --- a/lib/smarty/libs/sysplugins/smarty_variable.php +++ b/lib/smarty/libs/sysplugins/smarty_variable.php @@ -7,6 +7,7 @@ * @package Smarty * @subpackage Template */ +#[\AllowDynamicProperties] class Smarty_Variable { /** diff --git a/lib/smarty/libs/sysplugins/smartycompilerexception.php b/lib/smarty/libs/sysplugins/smartycompilerexception.php index 8833aa52..0a0a3235 100644 --- a/lib/smarty/libs/sysplugins/smartycompilerexception.php +++ b/lib/smarty/libs/sysplugins/smartycompilerexception.php @@ -7,6 +7,33 @@ */ class SmartyCompilerException extends SmartyException { + /** + * The constructor of the exception + * + * @param string $message The Exception message to throw. + * @param int $code The Exception code. + * @param string|null $filename The filename where the exception is thrown. + * @param int|null $line The line number where the exception is thrown. + * @param Throwable|null $previous The previous exception used for the exception chaining. + */ + public function __construct( + string $message = "", + int $code = 0, + ?string $filename = null, + ?int $line = null, + Throwable $previous = null + ) { + parent::__construct($message, $code, $previous); + + // These are optional parameters, should be be overridden only when present! + if ($filename) { + $this->file = $filename; + } + if ($line) { + $this->line = $line; + } + } + /** * @return string */ @@ -22,6 +49,7 @@ class SmartyCompilerException extends SmartyException { $this->line = $line; } + /** * The template source snippet relating to the error * diff --git a/lib/smarty/smarty_version b/lib/smarty/smarty_version index 6fa04898..1d2e7d6e 100644 --- a/lib/smarty/smarty_version +++ b/lib/smarty/smarty_version @@ -1,5 +1,5 @@ $Id$ -Smarty version: 4.1.1 +Smarty version: 4.3.0 (released: 2022/11/22) -https://github.com/smarty-php/smarty/archive/refs/tags/v4.1.1.tar.gz +https://github.com/smarty-php/smarty/archive/refs/tags/v4.3.0.tar.gz

#{$vars@key}#

- {if isset($vars['scope'])}Origin: {$vars['scope']|debug_print_var nofilter}{/if} +
+

#{$vars@key}#

+ {if isset($vars['scope'])}Origin: {$vars['scope']|debug_print_var nofilter}{/if} +
+ {$vars['value']|debug_print_var:10:80 nofilter} {$vars['value']|debug_print_var:10:80 nofilter}