mirror of
https://github.com/smarty-php/smarty.git
synced 2026-08-09 23:11:30 +02:00
Compare commits
70
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffa2b81a8e | ||
|
|
c693d81370 | ||
|
|
813c83f7a3 | ||
|
|
55ea25d1f5 | ||
|
|
d304d349b4 | ||
|
|
7494818434 | ||
|
|
50d5890eac | ||
|
|
6872e78238 | ||
|
|
5479e3362c | ||
|
|
f8f97b4e2d | ||
|
|
1bc7c722a3 | ||
|
|
02968a82b5 | ||
|
|
97aeb14c6f | ||
|
|
ed454551a3 | ||
|
|
f4b26a3cbf | ||
|
|
20a8026ccd | ||
|
|
27910bf2c1 | ||
|
|
cb95216671 | ||
|
|
d6ac3297df | ||
|
|
560475a2f2 | ||
|
|
382d66305d | ||
|
|
44bac8d58c | ||
|
|
f8e1ba76f7 | ||
|
|
629504485f | ||
|
|
71036be8be | ||
|
|
78f0cf5f65 | ||
|
|
64ad6442ca | ||
|
|
7eff7d6fb0 | ||
|
|
05f1a7deda | ||
|
|
3f97b7352e | ||
|
|
a6711b3833 | ||
|
|
52056ce65a | ||
|
|
8b96efad45 | ||
|
|
bfa02f3b91 | ||
|
|
89dc506638 | ||
|
|
e68065bc33 | ||
|
|
db2547287c | ||
|
|
962f266483 | ||
|
|
8aeb5d6821 | ||
|
|
a2e1df1768 | ||
|
|
fe6d333c60 | ||
|
|
50c4604857 | ||
|
|
e5a6ff42f8 | ||
|
|
3cc56392c6 | ||
|
|
17025423e1 | ||
|
|
18d3e564da | ||
|
|
0d2c38b482 | ||
|
|
f90348971b | ||
|
|
9e0536de18 | ||
|
|
265cf4f3bc | ||
|
|
47f95ad324 | ||
|
|
02633ecaba | ||
|
|
6786623afb | ||
|
|
2d97169086 | ||
|
|
0f098802c6 | ||
|
|
bbcd5817f6 | ||
|
|
612094d763 | ||
|
|
0ef0dda825 | ||
|
|
cef8951100 | ||
|
|
323aefa89f | ||
|
|
277648b81c | ||
|
|
8d3a7af308 | ||
|
|
cdf0f2b164 | ||
|
|
995b7eb36f | ||
|
|
059bea274c | ||
|
|
f707dadecb | ||
|
|
ace1c8e90f | ||
|
|
19ae410bf5 | ||
|
|
baad3115cd | ||
|
|
dff1955cd5 |
+6
-2
@@ -7,8 +7,12 @@
|
|||||||
|
|
||||||
# exclude from git export
|
# exclude from git export
|
||||||
/tests export-ignore
|
/tests export-ignore
|
||||||
/utilities/ export-ignore
|
/demo export-ignore
|
||||||
|
/docs export-ignore
|
||||||
|
/utilities export-ignore
|
||||||
|
/docker-compose.yml export-ignore
|
||||||
|
/.github export-ignore
|
||||||
|
/run_tests_for_all_php_versions.sh export-ignore
|
||||||
/.gitattributes export-ignore
|
/.gitattributes export-ignore
|
||||||
/.gitignore export-ignore
|
/.gitignore export-ignore
|
||||||
/make-release.sh export-ignore
|
/make-release.sh export-ignore
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
|
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
|
||||||
|
|
||||||
on:
|
on:
|
||||||
- pull_request
|
pull_request:
|
||||||
- push
|
push:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
|
||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
@@ -28,6 +30,7 @@ jobs:
|
|||||||
- "7.3"
|
- "7.3"
|
||||||
- "7.4"
|
- "7.4"
|
||||||
- "8.0"
|
- "8.0"
|
||||||
|
- "8.1"
|
||||||
|
|
||||||
compiler:
|
compiler:
|
||||||
- default
|
- default
|
||||||
@@ -36,6 +39,9 @@ jobs:
|
|||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
php-version: "8.0"
|
php-version: "8.0"
|
||||||
compiler: jit
|
compiler: jit
|
||||||
|
- os: ubuntu-latest
|
||||||
|
php-version: "8.1"
|
||||||
|
compiler: jit
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
lexer/*.php
|
lexer/*.php
|
||||||
lexer/*.php.bak
|
lexer/*.php.bak
|
||||||
lexer/*.out
|
lexer/*.out
|
||||||
utilies/*.php
|
|
||||||
|
|
||||||
# Dev
|
# Dev
|
||||||
phpunit*
|
phpunit*
|
||||||
|
|||||||
@@ -6,6 +6,54 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [4.2.1] - 2022-09-14
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Applied appropriate javascript and html escaping in mailto plugin to counter injection attacks [#454](https://github.com/smarty-php/smarty/issues/454)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed PHP8.1 deprecation errors in modifiers (upper, explode, number_format and replace) [#755](https://github.com/smarty-php/smarty/pull/755) and [#788](https://github.com/smarty-php/smarty/pull/788)
|
||||||
|
- Fixed PHP8.1 deprecation errors in capitalize modifier [#789](https://github.com/smarty-php/smarty/issues/789)
|
||||||
|
- Fixed use of `rand()` without a parameter in math function [#794](https://github.com/smarty-php/smarty/issues/794)
|
||||||
|
- Fixed unselected year/month/day not working in html_select_date [#395](https://github.com/smarty-php/smarty/issues/395)
|
||||||
|
|
||||||
|
## [4.2.0] - 2022-08-01
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed problems with smarty_mb_str_replace [#549](https://github.com/smarty-php/smarty/issues/549)
|
||||||
|
- Fixed second parameter of unescape modifier not working [#777](https://github.com/smarty-php/smarty/issues/777)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Updated HTML of the debug template [#599](https://github.com/smarty-php/smarty/pull/599)
|
||||||
|
|
||||||
|
## [4.1.1] - 2022-05-17
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Prevent PHP injection through malicious block name or include file name. This addresses CVE-2022-29221
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Exclude docs and demo from export and composer [#751](https://github.com/smarty-php/smarty/pull/751)
|
||||||
|
- PHP 8.1 deprecation notices in demo/plugins/cacheresource.pdo.php [#706](https://github.com/smarty-php/smarty/issues/706)
|
||||||
|
- PHP 8.1 deprecation notices in truncate modifier [#699](https://github.com/smarty-php/smarty/issues/699)
|
||||||
|
- Math equation `max(x, y)` didn't work anymore [#721](https://github.com/smarty-php/smarty/issues/721)
|
||||||
|
- Fix PHP 8.1 deprecated warning when calling rtrim [#743](https://github.com/smarty-php/smarty/pull/743)
|
||||||
|
- PHP 8.1: fix deprecation in escape modifier [#727](https://github.com/smarty-php/smarty/pull/727)
|
||||||
|
|
||||||
|
## [4.1.0] - 2022-02-06
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- PHP8.1 compatibility [#713](https://github.com/smarty-php/smarty/pull/713)
|
||||||
|
|
||||||
|
## [4.0.4] - 2022-01-18
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed illegal characters bug in math function security check [#702](https://github.com/smarty-php/smarty/issues/702)
|
||||||
|
|
||||||
|
## [4.0.3] - 2022-01-10
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Prevent evasion of the `static_classes` security policy. This addresses CVE-2021-21408
|
||||||
|
|
||||||
## [4.0.2] - 2022-01-10
|
## [4.0.2] - 2022-01-10
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Smarty is a template engine for PHP, facilitating the separation of presentation
|
|||||||
Read the [documentation](https://smarty-php.github.io/smarty/) to find out how to use it.
|
Read the [documentation](https://smarty-php.github.io/smarty/) to find out how to use it.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
Smarty can be run with PHP 7.1 to PHP 8.0.
|
Smarty can be run with PHP 7.1 to PHP 8.1.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/).
|
Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/).
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Supported Versions
|
## Supported Versions
|
||||||
|
|
||||||
Smarty currently supports the latest minor version of Smarty 3 and Smarty 4. (Smarty 4 has not been released yet.)
|
Smarty currently supports the latest minor version of Smarty 3 and Smarty 4.
|
||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ------- | ------------------ |
|
| ------- | ------------------ |
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom
|
|||||||
* @return void
|
* @return void
|
||||||
* @access protected
|
* @access protected
|
||||||
*/
|
*/
|
||||||
protected function fetch($id, $name, $cache_id = null, $compile_id = null, &$content, &$mtime)
|
protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime)
|
||||||
{
|
{
|
||||||
$stmt = $this->getFetchStatement($this->fetchColumns, $id, $cache_id, $compile_id);
|
$stmt = $this->getFetchStatement($this->fetchColumns, $id, $cache_id, $compile_id);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
@@ -244,7 +244,7 @@ class Smarty_CacheResource_Pdo extends Smarty_CacheResource_Custom
|
|||||||
* @return boolean success
|
* @return boolean success
|
||||||
* @access protected
|
* @access protected
|
||||||
*/
|
*/
|
||||||
protected function save($id, $name, $cache_id = null, $compile_id = null, $exp_time, $content)
|
protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content)
|
||||||
{
|
{
|
||||||
$stmt = $this->pdo->prepare($this->insertStatement);
|
$stmt = $this->pdo->prepare($this->insertStatement);
|
||||||
$stmt->bindValue('id', $id);
|
$stmt->bindValue('id', $id);
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
version: "2"
|
||||||
|
services:
|
||||||
|
base:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: ./utilities/testrunners/php71/Dockerfile
|
||||||
|
volumes:
|
||||||
|
- .:/app
|
||||||
|
working_dir: /app
|
||||||
|
entrypoint: sh ./utilities/testrunners/run-test.sh
|
||||||
|
php71:
|
||||||
|
extends:
|
||||||
|
service: base
|
||||||
|
build:
|
||||||
|
dockerfile: ./utilities/testrunners/php71/Dockerfile
|
||||||
|
php72:
|
||||||
|
extends:
|
||||||
|
service: base
|
||||||
|
build:
|
||||||
|
dockerfile: ./utilities/testrunners/php72/Dockerfile
|
||||||
|
php73:
|
||||||
|
extends:
|
||||||
|
service: base
|
||||||
|
build:
|
||||||
|
dockerfile: ./utilities/testrunners/php73/Dockerfile
|
||||||
|
php74:
|
||||||
|
extends:
|
||||||
|
service: base
|
||||||
|
build:
|
||||||
|
dockerfile: ./utilities/testrunners/php74/Dockerfile
|
||||||
|
php80:
|
||||||
|
extends:
|
||||||
|
service: base
|
||||||
|
build:
|
||||||
|
dockerfile: ./utilities/testrunners/php80/Dockerfile
|
||||||
|
php81:
|
||||||
|
extends:
|
||||||
|
service: base
|
||||||
|
build:
|
||||||
|
dockerfile: ./utilities/testrunners/php81/Dockerfile
|
||||||
@@ -2,7 +2,7 @@ What is Smarty?
|
|||||||
==============
|
==============
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
Smarty can be run with PHP 7.1 to PHP 8.0.
|
Smarty can be run with PHP 7.1 to PHP 8.1.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/).
|
Smarty versions 3.1.11 or later can be installed with [Composer](https://getcomposer.org/).
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
Setting `$escape_html` to TRUE will escape all template variable output
|
Setting `$escape_html` to TRUE will escape all template variable output
|
||||||
by wrapping it in
|
by wrapping it in
|
||||||
`htmlspecialchars({$output}, ENT_QUOTES, SMARTY_RESOURCE_CHAR_SET);`,
|
`htmlspecialchars({$output}, ENT_QUOTES, $char_set);`,
|
||||||
which is the same as `{$variable|escape:"html"}`.
|
which is the same as `{$variable|escape:"html"}`.
|
||||||
|
|
||||||
Template designers can choose to selectively disable this feature by
|
Template designers can choose to selectively disable this feature by
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ Charset Encoding {#charset.encoding}
|
|||||||
================
|
================
|
||||||
|
|
||||||
There are a variety of encodings for textual data, ISO-8859-1 (Latin1)
|
There are a variety of encodings for textual data, ISO-8859-1 (Latin1)
|
||||||
and UTF-8 being the most popular. Unless specified otherwise with the
|
and UTF-8 being the most popular. Unless you change `Smarty::$_CHARSET`,
|
||||||
`SMARTY_RESOURCE_CHAR_SET` constant, Smarty recognizes `UTF-8` as the
|
Smarty recognizes `UTF-8` as the internal charset if
|
||||||
internal charset if [Multibyte String](https://www.php.net/mbstring) is
|
[Multibyte String](https://www.php.net/mbstring) is available,
|
||||||
available, `ISO-8859-1` if not.
|
`ISO-8859-1` if not.
|
||||||
|
|
||||||
> **Note**
|
> **Note**
|
||||||
>
|
>
|
||||||
@@ -36,8 +36,9 @@ available, `ISO-8859-1` if not.
|
|||||||
if (function_exists('mb_internal_charset')) {
|
if (function_exists('mb_internal_charset')) {
|
||||||
mb_internal_charset('EUC-JP');
|
mb_internal_charset('EUC-JP');
|
||||||
}
|
}
|
||||||
define('SMARTY_RESOURCE_CHAR_SET', 'EUC-JP');
|
|
||||||
require_once 'libs/Smarty.class.php';
|
require_once 'libs/Smarty.class.php';
|
||||||
|
Smarty::$_CHARSET = 'EUC-JP';
|
||||||
$smarty = new Smarty();
|
$smarty = new Smarty();
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -747,6 +747,9 @@ value(res) ::= doublequoted_with_quotes(s). {
|
|||||||
|
|
||||||
|
|
||||||
value(res) ::= varindexed(vi) DOUBLECOLON static_class_access(r). {
|
value(res) ::= varindexed(vi) DOUBLECOLON static_class_access(r). {
|
||||||
|
if ($this->security && $this->security->static_classes !== array()) {
|
||||||
|
$this->compiler->trigger_template_error('dynamic static class not allowed by security setting');
|
||||||
|
}
|
||||||
$prefixVar = $this->compiler->getNewPrefixVariable();
|
$prefixVar = $this->compiler->getNewPrefixVariable();
|
||||||
if (vi['var'] === '\'smarty\'') {
|
if (vi['var'] === '\'smarty\'') {
|
||||||
$this->compiler->appendPrefixCode("<?php {$prefixVar} = ". $this->compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']).';?>');
|
$this->compiler->appendPrefixCode("<?php {$prefixVar} = ". $this->compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']).';?>');
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ class Smarty extends Smarty_Internal_TemplateBase
|
|||||||
/**
|
/**
|
||||||
* smarty version
|
* smarty version
|
||||||
*/
|
*/
|
||||||
const SMARTY_VERSION = '4.0.2';
|
const SMARTY_VERSION = '4.2.1';
|
||||||
/**
|
/**
|
||||||
* define variable scopes
|
* define variable scopes
|
||||||
*/
|
*/
|
||||||
@@ -867,7 +867,7 @@ class Smarty extends Smarty_Internal_TemplateBase
|
|||||||
$this->plugins_dir = (array)$this->plugins_dir;
|
$this->plugins_dir = (array)$this->plugins_dir;
|
||||||
}
|
}
|
||||||
foreach ($this->plugins_dir as $k => $v) {
|
foreach ($this->plugins_dir as $k => $v) {
|
||||||
$this->plugins_dir[ $k ] = $this->_realpath(rtrim($v, '/\\') . DIRECTORY_SEPARATOR, true);
|
$this->plugins_dir[ $k ] = $this->_realpath(rtrim($v ?? '', '/\\') . DIRECTORY_SEPARATOR, true);
|
||||||
}
|
}
|
||||||
$this->_cache[ 'plugin_files' ] = array();
|
$this->_cache[ 'plugin_files' ] = array();
|
||||||
$this->_pluginsDirNormalized = true;
|
$this->_pluginsDirNormalized = true;
|
||||||
@@ -1345,7 +1345,7 @@ class Smarty extends Smarty_Internal_TemplateBase
|
|||||||
*/
|
*/
|
||||||
private function _normalizeDir($dirName, $dir)
|
private function _normalizeDir($dirName, $dir)
|
||||||
{
|
{
|
||||||
$this->{$dirName} = $this->_realpath(rtrim($dir, "/\\") . DIRECTORY_SEPARATOR, true);
|
$this->{$dirName} = $this->_realpath(rtrim($dir ?? '', "/\\") . DIRECTORY_SEPARATOR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1367,7 +1367,7 @@ class Smarty extends Smarty_Internal_TemplateBase
|
|||||||
}
|
}
|
||||||
foreach ($dir as $k => $v) {
|
foreach ($dir as $k => $v) {
|
||||||
if (!isset($processed[ $k ])) {
|
if (!isset($processed[ $k ])) {
|
||||||
$dir[ $k ] = $v = $this->_realpath(rtrim($v, "/\\") . DIRECTORY_SEPARATOR, true);
|
$dir[ $k ] = $v = $this->_realpath(rtrim($v ?? '', "/\\") . DIRECTORY_SEPARATOR, true);
|
||||||
$processed[ $k ] = true;
|
$processed[ $k ] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-19
@@ -1,9 +1,9 @@
|
|||||||
{capture name='_smarty_debug' assign=debug_output}
|
{capture name='_smarty_debug' assign=debug_output}
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
<!DOCTYPE html>
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>Smarty Debug Console</title>
|
<title>Smarty Debug Console</title>
|
||||||
<style type="text/css">
|
<style>
|
||||||
{literal}
|
{literal}
|
||||||
body, h1, h2, h3, td, th, p {
|
body, h1, h2, h3, td, th, p {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
padding: 2px;
|
padding: 2px;
|
||||||
border-top: 1px solid black;
|
border-top: 1px solid black;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -67,11 +68,11 @@
|
|||||||
color: green;
|
color: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
.odd {
|
tr:nth-child(odd) {
|
||||||
background-color: #eeeeee;
|
background-color: #eeeeee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.even {
|
tr:nth-child(even) {
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,13 +85,16 @@
|
|||||||
color: black;
|
color: black;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
#blue h3 {
|
#blue h3 {
|
||||||
color: blue;
|
color: blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#normal div {
|
#normal div {
|
||||||
color: black;
|
color: black;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
#table_assigned_vars th {
|
#table_assigned_vars th {
|
||||||
color: blue;
|
color: blue;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -99,7 +103,6 @@
|
|||||||
#table_config_vars th {
|
#table_config_vars th {
|
||||||
color: maroon;
|
color: maroon;
|
||||||
}
|
}
|
||||||
|
|
||||||
{/literal}
|
{/literal}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@@ -112,11 +115,11 @@
|
|||||||
<h2>included templates & config files (load time in seconds)</h2>
|
<h2>included templates & config files (load time in seconds)</h2>
|
||||||
<div>
|
<div>
|
||||||
{foreach $template_data as $template}
|
{foreach $template_data as $template}
|
||||||
<font color=brown>{$template.name}</font>
|
<span style="color: brown;">{$template.name}</span>
|
||||||
<br /> <span class="exectime">
|
<br> <span class="exectime">
|
||||||
(compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"})
|
(compile {$template['compile_time']|string_format:"%.5f"}) (render {$template['render_time']|string_format:"%.5f"}) (cache {$template['cache_time']|string_format:"%.5f"})
|
||||||
</span>
|
</span>
|
||||||
<br />
|
<br>
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -125,13 +128,22 @@
|
|||||||
|
|
||||||
<table id="table_assigned_vars">
|
<table id="table_assigned_vars">
|
||||||
{foreach $assigned_vars as $vars}
|
{foreach $assigned_vars as $vars}
|
||||||
<tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
|
<tr>
|
||||||
<td><h3><font color=blue>${$vars@key}</font></h3>
|
<td>
|
||||||
{if isset($vars['nocache'])}<b>Nocache</b><br />{/if}
|
<h3 style="color: blue;">${$vars@key}</h3>
|
||||||
{if isset($vars['scope'])}<b>Origin:</b> {$vars['scope']|debug_print_var nofilter}{/if}
|
{if isset($vars['nocache'])}<strong>Nocache</strong><br>{/if}
|
||||||
|
{if isset($vars['scope'])}<strong>Origin:</strong> {$vars['scope']|debug_print_var nofilter}{/if}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<h3>Value</h3>
|
||||||
|
{$vars['value']|debug_print_var:10:80 nofilter}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{if isset($vars['attributes'])}
|
||||||
|
<h3>Attributes</h3>
|
||||||
|
{$vars['attributes']|debug_print_var nofilter}
|
||||||
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
<td><h3>Value</h3>{$vars['value']|debug_print_var:10:80 nofilter}</td>
|
|
||||||
<td>{if isset($vars['attributes'])}<h3>Attributes</h3>{$vars['attributes']|debug_print_var nofilter} {/if}</td>
|
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@@ -139,11 +151,14 @@
|
|||||||
|
|
||||||
<table id="table_config_vars">
|
<table id="table_config_vars">
|
||||||
{foreach $config_vars as $vars}
|
{foreach $config_vars as $vars}
|
||||||
<tr class="{if $vars@iteration % 2 eq 0}odd{else}even{/if}">
|
<tr>
|
||||||
<td><h3><font color=blue>#{$vars@key}#</font></h3>
|
<td>
|
||||||
{if isset($vars['scope'])}<b>Origin:</b> {$vars['scope']|debug_print_var nofilter}{/if}
|
<h3 style="color: blue;">#{$vars@key}#</h3>
|
||||||
|
{if isset($vars['scope'])}<strong>Origin:</strong> {$vars['scope']|debug_print_var nofilter}{/if}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{$vars['value']|debug_print_var:10:80 nofilter}
|
||||||
</td>
|
</td>
|
||||||
<td>{$vars['value']|debug_print_var:10:80 nofilter}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{/foreach}
|
{/foreach}
|
||||||
|
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ function smarty_function_html_select_date($params, Smarty_Internal_Template $tem
|
|||||||
$field_separator = "\n";
|
$field_separator = "\n";
|
||||||
$option_separator = "\n";
|
$option_separator = "\n";
|
||||||
$time = null;
|
$time = null;
|
||||||
|
|
||||||
// $all_empty = null;
|
// $all_empty = null;
|
||||||
// $day_empty = null;
|
// $day_empty = null;
|
||||||
// $month_empty = null;
|
// $month_empty = null;
|
||||||
@@ -113,17 +114,7 @@ function smarty_function_html_select_date($params, Smarty_Internal_Template $tem
|
|||||||
foreach ($params as $_key => $_value) {
|
foreach ($params as $_key => $_value) {
|
||||||
switch ($_key) {
|
switch ($_key) {
|
||||||
case 'time':
|
case 'time':
|
||||||
if (!is_array($_value) && $_value !== null) {
|
$$_key = $_value; // we'll handle conversion below
|
||||||
$template->_checkPlugins(
|
|
||||||
array(
|
|
||||||
array(
|
|
||||||
'function' => 'smarty_make_timestamp',
|
|
||||||
'file' => SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
$time = smarty_make_timestamp($_value);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'month_names':
|
case 'month_names':
|
||||||
if (is_array($_value) && count($_value) === 12) {
|
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: date() is faster than strftime()
|
||||||
// Note: explode(date()) is faster than date() date() date()
|
// 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
|
// $_REQUEST[$field_array] given
|
||||||
foreach (array(
|
foreach ([
|
||||||
'Y' => 'Year',
|
'Y' => 'Year',
|
||||||
'm' => 'Month',
|
'm' => 'Month',
|
||||||
'd' => 'Day'
|
'd' => 'Day'
|
||||||
) as $_elementKey => $_elementName) {
|
] as $_elementKey => $_elementName) {
|
||||||
$_variableName = '_' . strtolower($_elementName);
|
$_variableName = '_' . strtolower($_elementName);
|
||||||
$$_variableName =
|
$$_variableName =
|
||||||
isset($params[ 'time' ][ $prefix . $_elementName ]) ? $params[ 'time' ][ $prefix . $_elementName ] :
|
isset($time[$prefix . $_elementName]) ? $time[$prefix . $_elementName] :
|
||||||
date($_elementKey);
|
date($_elementKey);
|
||||||
}
|
}
|
||||||
} elseif (isset($params[ 'time' ][ $field_array ][ $prefix . 'Year' ])) {
|
} elseif (isset($time[$field_array][$prefix . 'Year'])) {
|
||||||
// $_REQUEST given
|
// $_REQUEST given
|
||||||
foreach (array(
|
foreach ([
|
||||||
'Y' => 'Year',
|
'Y' => 'Year',
|
||||||
'm' => 'Month',
|
'm' => 'Month',
|
||||||
'd' => 'Day'
|
'd' => 'Day'
|
||||||
) as $_elementKey => $_elementName) {
|
] as $_elementKey => $_elementName) {
|
||||||
$_variableName = '_' . strtolower($_elementName);
|
$_variableName = '_' . strtolower($_elementName);
|
||||||
$$_variableName = isset($params[ 'time' ][ $field_array ][ $prefix . $_elementName ]) ?
|
$$_variableName = isset($time[$field_array][$prefix . $_elementName]) ?
|
||||||
$params[ 'time' ][ $field_array ][ $prefix . $_elementName ] : date($_elementKey);
|
$time[$field_array][$prefix . $_elementName] : date($_elementKey);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no date found, use NOW
|
// 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) {
|
} elseif ($time === null) {
|
||||||
if (array_key_exists('time', $params)) {
|
if (array_key_exists('time', $params)) {
|
||||||
$_year = $_month = $_day = $time = null;
|
$_year = $_month = $_day = null;
|
||||||
} else {
|
} else {
|
||||||
list($_year, $_month, $_day) = $time = explode('-', date('Y-m-d'));
|
[$_year, $_month, $_day] = explode('-', date('Y-m-d'));
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
// 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
|
// Note preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match) is slower than trim+substr
|
||||||
foreach (array(
|
foreach (array(
|
||||||
|
|||||||
@@ -48,8 +48,13 @@
|
|||||||
*/
|
*/
|
||||||
function smarty_function_mailto($params)
|
function smarty_function_mailto($params)
|
||||||
{
|
{
|
||||||
static $_allowed_encoding =
|
static $_allowed_encoding = [
|
||||||
array('javascript' => true, 'javascript_charcode' => true, 'hex' => true, 'none' => true);
|
'javascript' => true,
|
||||||
|
'javascript_charcode' => true,
|
||||||
|
'hex' => true,
|
||||||
|
'none' => true
|
||||||
|
];
|
||||||
|
|
||||||
$extra = '';
|
$extra = '';
|
||||||
if (empty($params[ 'address' ])) {
|
if (empty($params[ 'address' ])) {
|
||||||
trigger_error("mailto: missing 'address' parameter", E_USER_WARNING);
|
trigger_error("mailto: missing 'address' parameter", E_USER_WARNING);
|
||||||
@@ -57,19 +62,19 @@ function smarty_function_mailto($params)
|
|||||||
} else {
|
} else {
|
||||||
$address = $params[ 'address' ];
|
$address = $params[ 'address' ];
|
||||||
}
|
}
|
||||||
|
|
||||||
$text = $address;
|
$text = $address;
|
||||||
|
|
||||||
// netscape and mozilla do not decode %40 (@) in BCC field (bug?)
|
// netscape and mozilla do not decode %40 (@) in BCC field (bug?)
|
||||||
// so, don't encode it.
|
// so, don't encode it.
|
||||||
$search = array('%40', '%2C');
|
$mail_parms = [];
|
||||||
$replace = array('@', ',');
|
|
||||||
$mail_parms = array();
|
|
||||||
foreach ($params as $var => $value) {
|
foreach ($params as $var => $value) {
|
||||||
switch ($var) {
|
switch ($var) {
|
||||||
case 'cc':
|
case 'cc':
|
||||||
case 'bcc':
|
case 'bcc':
|
||||||
case 'followupto':
|
case 'followupto':
|
||||||
if (!empty($value)) {
|
if (!empty($value)) {
|
||||||
$mail_parms[] = $var . '=' . str_replace($search, $replace, rawurlencode($value));
|
$mail_parms[] = $var . '=' . str_replace(['%40', '%2C'], ['@', ','], rawurlencode($value));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'subject':
|
case 'subject':
|
||||||
@@ -83,6 +88,7 @@ function smarty_function_mailto($params)
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($mail_parms) {
|
if ($mail_parms) {
|
||||||
$address .= '?' . join('&', $mail_parms);
|
$address .= '?' . join('&', $mail_parms);
|
||||||
}
|
}
|
||||||
@@ -94,19 +100,21 @@ function smarty_function_mailto($params)
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$string = '<a href="mailto:' . htmlspecialchars($address, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, Smarty::$_CHARSET) .
|
||||||
|
'" ' . $extra . '>' . htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, Smarty::$_CHARSET) . '</a>';
|
||||||
|
|
||||||
if ($encode === 'javascript') {
|
if ($encode === 'javascript') {
|
||||||
$string = '<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>';
|
|
||||||
$js_encode = '';
|
$js_encode = '';
|
||||||
for ($x = 0, $_length = strlen($string); $x < $_length; $x++) {
|
for ($x = 0, $_length = strlen($string); $x < $_length; $x++) {
|
||||||
$js_encode .= '%' . bin2hex($string[ $x ]);
|
$js_encode .= '%' . bin2hex($string[ $x ]);
|
||||||
}
|
}
|
||||||
return '<script type="text/javascript">document.write(unescape(\'' . $js_encode . '\'))</script>';
|
return '<script type="text/javascript">document.write(unescape(\'' . $js_encode . '\'))</script>';
|
||||||
} elseif ($encode === 'javascript_charcode') {
|
} elseif ($encode === 'javascript_charcode') {
|
||||||
$string = '<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>';
|
|
||||||
for ($x = 0, $_length = strlen($string); $x < $_length; $x++) {
|
for ($x = 0, $_length = strlen($string); $x < $_length; $x++) {
|
||||||
$ord[] = ord($string[ $x ]);
|
$ord[] = ord($string[ $x ]);
|
||||||
}
|
}
|
||||||
return '<script type="text/javascript">document.write(String.fromCharCode(' . implode(',', $ord) . '))</script>';
|
return '<script type="text/javascript">document.write(String.fromCharCode(' . implode(',', $ord) . '))</script>';
|
||||||
} elseif ($encode === 'hex') {
|
} elseif ($encode === 'hex') {
|
||||||
preg_match('!^(.*)(\?.*)$!', $address, $match);
|
preg_match('!^(.*)(\?.*)$!', $address, $match);
|
||||||
if (!empty($match[ 2 ])) {
|
if (!empty($match[ 2 ])) {
|
||||||
@@ -129,6 +137,6 @@ function smarty_function_mailto($params)
|
|||||||
return '<a href="' . $mailto . $address_encode . '" ' . $extra . '>' . $text_encode . '</a>';
|
return '<a href="' . $mailto . $address_encode . '" ' . $extra . '>' . $text_encode . '</a>';
|
||||||
} else {
|
} else {
|
||||||
// no encoding
|
// no encoding
|
||||||
return '<a href="mailto:' . $address . '" ' . $extra . '>' . $text . '</a>';
|
return $string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,8 +69,8 @@ function smarty_function_math($params, $template)
|
|||||||
// Adapted from https://www.php.net/manual/en/function.eval.php#107377
|
// Adapted from https://www.php.net/manual/en/function.eval.php#107377
|
||||||
$number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number
|
$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]*))';
|
$functionsOrVars = '((?:0x[a-fA-F0-9]+)|([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*))';
|
||||||
$operators = '[+\/*\^%-]'; // Allowed math operators
|
$operators = '[,+\/*\^%-]'; // Allowed math operators
|
||||||
$regexp = '/^(('.$number.'|'.$functionsOrVars.'|('.$functionsOrVars.'\s*\((?1)+\)|\((?1)+\)))(?:'.$operators.'(?2))?)+$/';
|
$regexp = '/^(('.$number.'|'.$functionsOrVars.'|('.$functionsOrVars.'\s*\((?1)*\)|\((?1)*\)))(?:'.$operators.'(?1))?)+$/';
|
||||||
|
|
||||||
if (!preg_match($regexp, $equation)) {
|
if (!preg_match($regexp, $equation)) {
|
||||||
trigger_error("math: illegal characters", E_USER_WARNING);
|
trigger_error("math: illegal characters", E_USER_WARNING);
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = false)
|
function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = false)
|
||||||
{
|
{
|
||||||
|
$string = (string) $string;
|
||||||
|
|
||||||
if (Smarty::$_MBSTRING) {
|
if (Smarty::$_MBSTRING) {
|
||||||
if ($lc_rest) {
|
if ($lc_rest) {
|
||||||
// uppercase (including hyphenated words)
|
// uppercase (including hyphenated words)
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $
|
|||||||
if (!$char_set) {
|
if (!$char_set) {
|
||||||
$char_set = Smarty::$_CHARSET;
|
$char_set = Smarty::$_CHARSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$string = (string)$string;
|
||||||
|
|
||||||
switch ($esc_type) {
|
switch ($esc_type) {
|
||||||
case 'html':
|
case 'html':
|
||||||
if ($_double_encode) {
|
if ($_double_encode) {
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Smarty plugin
|
||||||
|
*
|
||||||
|
* @package Smarty
|
||||||
|
* @subpackage PluginsModifier
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Smarty explode modifier plugin
|
||||||
|
* Type: modifier
|
||||||
|
* Name: explode
|
||||||
|
* Purpose: split a string by a string
|
||||||
|
*
|
||||||
|
* @param string $separator
|
||||||
|
* @param string $string
|
||||||
|
* @param int|null $limit
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function smarty_modifier_explode($separator, $string, ?int $limit = null)
|
||||||
|
{
|
||||||
|
// provide $string default to prevent deprecation errors in PHP >=8.1
|
||||||
|
return explode($separator, $string ?? '', $limit ?? PHP_INT_MAX);
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Smarty plugin
|
||||||
|
*
|
||||||
|
* @package Smarty
|
||||||
|
* @subpackage PluginsModifier
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Smarty number_format modifier plugin
|
||||||
|
* Type: modifier
|
||||||
|
* Name: number_format
|
||||||
|
* Purpose: Format a number with grouped thousands
|
||||||
|
*
|
||||||
|
* @param float|null $num
|
||||||
|
* @param int $decimals
|
||||||
|
* @param string|null $decimal_separator
|
||||||
|
* @param string|null $thousands_separator
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function smarty_modifier_number_format(?float $num, int $decimals = 0, ?string $decimal_separator = ".", ?string $thousands_separator = ",")
|
||||||
|
{
|
||||||
|
// provide $num default to prevent deprecation errors in PHP >=8.1
|
||||||
|
return number_format($num ?? 0.0, $decimals, $decimal_separator, $thousands_separator);
|
||||||
|
}
|
||||||
@@ -42,8 +42,8 @@ function smarty_modifier_truncate($string, $length = 80, $etc = '...', $break_wo
|
|||||||
if (!$middle) {
|
if (!$middle) {
|
||||||
return mb_substr($string, 0, $length, Smarty::$_CHARSET) . $etc;
|
return mb_substr($string, 0, $length, Smarty::$_CHARSET) . $etc;
|
||||||
}
|
}
|
||||||
return mb_substr($string, 0, $length / 2, Smarty::$_CHARSET) . $etc .
|
return mb_substr($string, 0, intval($length / 2), Smarty::$_CHARSET) . $etc .
|
||||||
mb_substr($string, -$length / 2, $length, Smarty::$_CHARSET);
|
mb_substr($string, -intval($length / 2), $length, Smarty::$_CHARSET);
|
||||||
}
|
}
|
||||||
return $string;
|
return $string;
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ function smarty_modifier_truncate($string, $length = 80, $etc = '...', $break_wo
|
|||||||
if (!$middle) {
|
if (!$middle) {
|
||||||
return substr($string, 0, $length) . $etc;
|
return substr($string, 0, $length) . $etc;
|
||||||
}
|
}
|
||||||
return substr($string, 0, $length / 2) . $etc . substr($string, -$length / 2);
|
return substr($string, 0, intval($length / 2)) . $etc . substr($string, -intval($length / 2));
|
||||||
}
|
}
|
||||||
return $string;
|
return $string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ function smarty_modifiercompiler_escape($params, Smarty_Internal_TemplateCompile
|
|||||||
switch ($esc_type) {
|
switch ($esc_type) {
|
||||||
case 'html':
|
case 'html':
|
||||||
if ($_double_encode) {
|
if ($_double_encode) {
|
||||||
return 'htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' .
|
return 'htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' .
|
||||||
var_export($double_encode, true) . ')';
|
var_export($double_encode, true) . ')';
|
||||||
} elseif ($double_encode) {
|
} elseif ($double_encode) {
|
||||||
return 'htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')';
|
return 'htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')';
|
||||||
} else {
|
} else {
|
||||||
// fall back to modifier.escape.php
|
// fall back to modifier.escape.php
|
||||||
}
|
}
|
||||||
@@ -54,12 +54,12 @@ function smarty_modifiercompiler_escape($params, Smarty_Internal_TemplateCompile
|
|||||||
if (Smarty::$_MBSTRING) {
|
if (Smarty::$_MBSTRING) {
|
||||||
if ($_double_encode) {
|
if ($_double_encode) {
|
||||||
// php >=5.2.3 - go native
|
// php >=5.2.3 - go native
|
||||||
return 'mb_convert_encoding(htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' .
|
return 'mb_convert_encoding(htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' .
|
||||||
var_export($char_set, true) . ', ' . var_export($double_encode, true) .
|
var_export($char_set, true) . ', ' . var_export($double_encode, true) .
|
||||||
'), "HTML-ENTITIES", ' . var_export($char_set, true) . ')';
|
'), "HTML-ENTITIES", ' . var_export($char_set, true) . ')';
|
||||||
} elseif ($double_encode) {
|
} elseif ($double_encode) {
|
||||||
// php <5.2.3 - only handle double encoding
|
// php <5.2.3 - only handle double encoding
|
||||||
return 'mb_convert_encoding(htmlspecialchars(' . $params[ 0 ] . ', ENT_QUOTES, ' .
|
return 'mb_convert_encoding(htmlspecialchars((string)' . $params[ 0 ] . ', ENT_QUOTES, ' .
|
||||||
var_export($char_set, true) . '), "HTML-ENTITIES", ' . var_export($char_set, true) . ')';
|
var_export($char_set, true) . '), "HTML-ENTITIES", ' . var_export($char_set, true) . ')';
|
||||||
} else {
|
} else {
|
||||||
// fall back to modifier.escape.php
|
// fall back to modifier.escape.php
|
||||||
@@ -68,26 +68,26 @@ function smarty_modifiercompiler_escape($params, Smarty_Internal_TemplateCompile
|
|||||||
// no MBString fallback
|
// no MBString fallback
|
||||||
if ($_double_encode) {
|
if ($_double_encode) {
|
||||||
// php >=5.2.3 - go native
|
// php >=5.2.3 - go native
|
||||||
return 'htmlentities(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' .
|
return 'htmlentities((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ', ' .
|
||||||
var_export($double_encode, true) . ')';
|
var_export($double_encode, true) . ')';
|
||||||
} elseif ($double_encode) {
|
} elseif ($double_encode) {
|
||||||
// php <5.2.3 - only handle double encoding
|
// php <5.2.3 - only handle double encoding
|
||||||
return 'htmlentities(' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')';
|
return 'htmlentities((string)' . $params[ 0 ] . ', ENT_QUOTES, ' . var_export($char_set, true) . ')';
|
||||||
} else {
|
} else {
|
||||||
// fall back to modifier.escape.php
|
// fall back to modifier.escape.php
|
||||||
}
|
}
|
||||||
// no break
|
// no break
|
||||||
case 'url':
|
case 'url':
|
||||||
return 'rawurlencode(' . $params[ 0 ] . ')';
|
return 'rawurlencode((string)' . $params[ 0 ] . ')';
|
||||||
case 'urlpathinfo':
|
case 'urlpathinfo':
|
||||||
return 'str_replace("%2F", "/", rawurlencode(' . $params[ 0 ] . '))';
|
return 'str_replace("%2F", "/", rawurlencode((string)' . $params[ 0 ] . '))';
|
||||||
case 'quotes':
|
case 'quotes':
|
||||||
// escape unescaped single quotes
|
// escape unescaped single quotes
|
||||||
return 'preg_replace("%(?<!\\\\\\\\)\'%", "\\\'",' . $params[ 0 ] . ')';
|
return 'preg_replace("%(?<!\\\\\\\\)\'%", "\\\'", (string)' . $params[ 0 ] . ')';
|
||||||
case 'javascript':
|
case 'javascript':
|
||||||
// escape quotes and backslashes, newlines, etc.
|
// escape quotes and backslashes, newlines, etc.
|
||||||
// see https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements
|
// see https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements
|
||||||
return 'strtr(' .
|
return 'strtr((string)' .
|
||||||
$params[ 0 ] .
|
$params[ 0 ] .
|
||||||
', array("\\\\" => "\\\\\\\\", "\'" => "\\\\\'", "\"" => "\\\\\"", "\\r" => "\\\\r", "\\n" => "\\\n", "</" => "<\/", "<!--" => "<\!--", "<s" => "<\s", "<S" => "<\S" ))';
|
', array("\\\\" => "\\\\\\\\", "\'" => "\\\\\'", "\"" => "\\\\\"", "\\r" => "\\\\r", "\\n" => "\\\n", "</" => "<\/", "<!--" => "<\!--", "<s" => "<\s", "<S" => "<\S" ))';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,20 +14,28 @@
|
|||||||
* @author Rodney Rehm
|
* @author Rodney Rehm
|
||||||
*
|
*
|
||||||
* @param array $params parameters
|
* @param array $params parameters
|
||||||
|
* @param Smarty_Internal_TemplateCompilerBase $compiler
|
||||||
*
|
*
|
||||||
* @return string with compiled code
|
* @return string with compiled code
|
||||||
*/
|
*/
|
||||||
function smarty_modifiercompiler_unescape($params)
|
function smarty_modifiercompiler_unescape($params, Smarty_Internal_TemplateCompilerBase $compiler)
|
||||||
{
|
{
|
||||||
if (!isset($params[ 1 ])) {
|
$compiler->template->_checkPlugins(
|
||||||
$params[ 1 ] = 'html';
|
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 ])) {
|
if (!isset($params[ 2 ])) {
|
||||||
$params[ 2 ] = '\'' . addslashes(Smarty::$_CHARSET) . '\'';
|
$params[ 2 ] = '\'' . addslashes(Smarty::$_CHARSET) . '\'';
|
||||||
} else {
|
|
||||||
$params[ 2 ] = "'{$params[ 2 ]}'";
|
|
||||||
}
|
}
|
||||||
switch (trim($params[ 1 ], '"\'')) {
|
|
||||||
|
switch ($esc_type) {
|
||||||
case 'entity':
|
case 'entity':
|
||||||
case 'htmlall':
|
case 'htmlall':
|
||||||
if (Smarty::$_MBSTRING) {
|
if (Smarty::$_MBSTRING) {
|
||||||
|
|||||||
@@ -21,8 +21,8 @@
|
|||||||
function smarty_modifiercompiler_upper($params)
|
function smarty_modifiercompiler_upper($params)
|
||||||
{
|
{
|
||||||
if (Smarty::$_MBSTRING) {
|
if (Smarty::$_MBSTRING) {
|
||||||
return 'mb_strtoupper(' . $params[ 0 ] . ', \'' . addslashes(Smarty::$_CHARSET) . '\')';
|
return 'mb_strtoupper(' . $params[ 0 ] . ' ?? \'\', \'' . addslashes(Smarty::$_CHARSET) . '\')';
|
||||||
}
|
}
|
||||||
// no MBString fallback
|
// no MBString fallback
|
||||||
return 'strtoupper(' . $params[ 0 ] . ')';
|
return 'strtoupper(' . $params[ 0 ] . ' ?? \'\')';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,9 +44,43 @@ if (!function_exists('smarty_mb_str_replace')) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
$count = count($parts) - 1;
|
||||||
$subject = implode($replace, $parts);
|
$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;
|
return $subject;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,8 +196,8 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource
|
|||||||
*/
|
*/
|
||||||
public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
|
public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached)
|
||||||
{
|
{
|
||||||
clearstatcache(true, $cached->lock_id);
|
clearstatcache(true, $cached->lock_id ?? '');
|
||||||
if (is_file($cached->lock_id)) {
|
if (null !== $cached->lock_id && is_file($cached->lock_id)) {
|
||||||
$t = filemtime($cached->lock_id);
|
$t = filemtime($cached->lock_id);
|
||||||
return $t && (time() - $t < $smarty->locking_timeout);
|
return $t && (time() - $t < $smarty->locking_timeout);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_Compile_Shared_
|
|||||||
// setup buffer for template function code
|
// setup buffer for template function code
|
||||||
$compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
|
$compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template();
|
||||||
$output = "<?php\n";
|
$output = "<?php\n";
|
||||||
$output .= "/* {block {$_name}} */\n";
|
$output .= $compiler->cStyleComment(" {block {$_name}} ") . "\n";
|
||||||
$output .= "class {$_className} extends Smarty_Internal_Block\n";
|
$output .= "class {$_className} extends Smarty_Internal_Block\n";
|
||||||
$output .= "{\n";
|
$output .= "{\n";
|
||||||
foreach ($_block as $property => $value) {
|
foreach ($_block as $property => $value) {
|
||||||
@@ -155,7 +155,7 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_Compile_Shared_
|
|||||||
}
|
}
|
||||||
$output .= "}\n";
|
$output .= "}\n";
|
||||||
$output .= "}\n";
|
$output .= "}\n";
|
||||||
$output .= "/* {/block {$_name}} */\n\n";
|
$output .= $compiler->cStyleComment(" {/block {$_name}} ") . "\n\n";
|
||||||
$output .= "?>\n";
|
$output .= "?>\n";
|
||||||
$compiler->parser->current_buffer->append_subtree(
|
$compiler->parser->current_buffer->append_subtree(
|
||||||
$compiler->parser,
|
$compiler->parser,
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
|
|||||||
if ($compiler->template->compiled->has_nocache_code) {
|
if ($compiler->template->compiled->has_nocache_code) {
|
||||||
$compiler->parent_compiler->tpl_function[ $_name ][ 'call_name_caching' ] = $_funcNameCaching;
|
$compiler->parent_compiler->tpl_function[ $_name ][ 'call_name_caching' ] = $_funcNameCaching;
|
||||||
$output = "<?php\n";
|
$output = "<?php\n";
|
||||||
$output .= "/* {$_funcNameCaching} */\n";
|
$output .= $compiler->cStyleComment(" {$_funcNameCaching} ") . "\n";
|
||||||
$output .= "if (!function_exists('{$_funcNameCaching}')) {\n";
|
$output .= "if (!function_exists('{$_funcNameCaching}')) {\n";
|
||||||
$output .= "function {$_funcNameCaching} (Smarty_Internal_Template \$_smarty_tpl,\$params) {\n";
|
$output .= "function {$_funcNameCaching} (Smarty_Internal_Template \$_smarty_tpl,\$params) {\n";
|
||||||
$output .= "ob_start();\n";
|
$output .= "ob_start();\n";
|
||||||
@@ -157,9 +157,9 @@ class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
|
|||||||
$output = "<?php echo \"/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/<?php ";
|
$output = "<?php echo \"/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/<?php ";
|
||||||
$output .= "\\\$_smarty_tpl->smarty->ext->_tplFunction->restoreTemplateVariables(\\\$_smarty_tpl, '{$_name}');?>\n";
|
$output .= "\\\$_smarty_tpl->smarty->ext->_tplFunction->restoreTemplateVariables(\\\$_smarty_tpl, '{$_name}');?>\n";
|
||||||
$output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\";\n?>";
|
$output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\";\n?>";
|
||||||
$output .= "<?php echo str_replace('{$compiler->template->compiled->nocache_hash}', \$_smarty_tpl->compiled->nocache_hash, ob_get_clean());\n";
|
$output .= "<?php echo str_replace('{$compiler->template->compiled->nocache_hash}', \$_smarty_tpl->compiled->nocache_hash ?? '', ob_get_clean());\n";
|
||||||
$output .= "}\n}\n";
|
$output .= "}\n}\n";
|
||||||
$output .= "/*/ {$_funcName}_nocache */\n\n";
|
$output .= $compiler->cStyleComment("/ {$_funcName}_nocache ") . "\n\n";
|
||||||
$output .= "?>\n";
|
$output .= "?>\n";
|
||||||
$compiler->parser->current_buffer->append_subtree(
|
$compiler->parser->current_buffer->append_subtree(
|
||||||
$compiler->parser,
|
$compiler->parser,
|
||||||
@@ -179,7 +179,7 @@ class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
|
|||||||
}
|
}
|
||||||
$compiler->parent_compiler->tpl_function[ $_name ][ 'call_name' ] = $_funcName;
|
$compiler->parent_compiler->tpl_function[ $_name ][ 'call_name' ] = $_funcName;
|
||||||
$output = "<?php\n";
|
$output = "<?php\n";
|
||||||
$output .= "/* {$_funcName} */\n";
|
$output .= $compiler->cStyleComment(" {$_funcName} ") . "\n";
|
||||||
$output .= "if (!function_exists('{$_funcName}')) {\n";
|
$output .= "if (!function_exists('{$_funcName}')) {\n";
|
||||||
$output .= "function {$_funcName}(Smarty_Internal_Template \$_smarty_tpl,\$params) {\n";
|
$output .= "function {$_funcName}(Smarty_Internal_Template \$_smarty_tpl,\$params) {\n";
|
||||||
$output .= $_paramsCode;
|
$output .= $_paramsCode;
|
||||||
@@ -196,7 +196,7 @@ class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase
|
|||||||
);
|
);
|
||||||
$compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
|
$compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode);
|
||||||
$output = "<?php\n}}\n";
|
$output = "<?php\n}}\n";
|
||||||
$output .= "/*/ {$_funcName} */\n\n";
|
$output .= $compiler->cStyleComment("/ {$_funcName} ") . "\n\n";
|
||||||
$output .= "?>\n";
|
$output .= "?>\n";
|
||||||
$compiler->parser->current_buffer->append_subtree(
|
$compiler->parser->current_buffer->append_subtree(
|
||||||
$compiler->parser,
|
$compiler->parser,
|
||||||
|
|||||||
@@ -318,14 +318,14 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
|
|||||||
}
|
}
|
||||||
// get compiled code
|
// get compiled code
|
||||||
$compiled_code = "<?php\n\n";
|
$compiled_code = "<?php\n\n";
|
||||||
$compiled_code .= "/* Start inline template \"{$sourceInfo}\" =============================*/\n";
|
$compiled_code .= $compiler->cStyleComment(" Start inline template \"{$sourceInfo}\" =============================") . "\n";
|
||||||
$compiled_code .= "function {$tpl->compiled->unifunc} (Smarty_Internal_Template \$_smarty_tpl) {\n";
|
$compiled_code .= "function {$tpl->compiled->unifunc} (Smarty_Internal_Template \$_smarty_tpl) {\n";
|
||||||
$compiled_code .= "?>\n" . $tpl->compiler->compileTemplateSource($tpl, null, $compiler->parent_compiler);
|
$compiled_code .= "?>\n" . $tpl->compiler->compileTemplateSource($tpl, null, $compiler->parent_compiler);
|
||||||
$compiled_code .= "<?php\n";
|
$compiled_code .= "<?php\n";
|
||||||
$compiled_code .= "}\n?>\n";
|
$compiled_code .= "}\n?>\n";
|
||||||
$compiled_code .= $tpl->compiler->postFilter($tpl->compiler->blockOrFunctionCode);
|
$compiled_code .= $tpl->compiler->postFilter($tpl->compiler->blockOrFunctionCode);
|
||||||
$compiled_code .= "<?php\n\n";
|
$compiled_code .= "<?php\n\n";
|
||||||
$compiled_code .= "/* End inline template \"{$sourceInfo}\" =============================*/\n";
|
$compiled_code .= $compiler->cStyleComment(" End inline template \"{$sourceInfo}\" =============================") . "\n";
|
||||||
$compiled_code .= '?>';
|
$compiled_code .= '?>';
|
||||||
unset($tpl->compiler);
|
unset($tpl->compiler);
|
||||||
if ($tpl->compiled->has_nocache_code) {
|
if ($tpl->compiled->has_nocache_code) {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase
|
|||||||
}
|
}
|
||||||
if (!empty($_dir)) {
|
if (!empty($_dir)) {
|
||||||
foreach ((array)$_dir as $_script_dir) {
|
foreach ((array)$_dir as $_script_dir) {
|
||||||
$_script_dir = rtrim($_script_dir, '/\\') . DIRECTORY_SEPARATOR;
|
$_script_dir = rtrim($_script_dir ?? '', '/\\') . DIRECTORY_SEPARATOR;
|
||||||
if (file_exists($_script_dir . $_script)) {
|
if (file_exists($_script_dir . $_script)) {
|
||||||
$_filepath = $_script_dir . $_script;
|
$_filepath = $_script_dir . $_script;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class Smarty_Internal_Compile_Private_Print_Expression extends Smarty_Internal_C
|
|||||||
}
|
}
|
||||||
// autoescape html
|
// autoescape html
|
||||||
if ($compiler->template->smarty->escape_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
|
// loop over registered filters
|
||||||
if (!empty($compiler->template->smarty->registered_filters[ Smarty::FILTER_VARIABLE ])) {
|
if (!empty($compiler->template->smarty->registered_filters[ Smarty::FILTER_VARIABLE ])) {
|
||||||
|
|||||||
@@ -157,10 +157,12 @@ class Smarty_Internal_Config_File_Compiler
|
|||||||
$this->smarty->_debug->end_compile($this->template);
|
$this->smarty->_debug->end_compile($this->template);
|
||||||
}
|
}
|
||||||
// template header code
|
// template header code
|
||||||
$template_header =
|
$template_header = sprintf(
|
||||||
"<?php /* Smarty version " . Smarty::SMARTY_VERSION . ", created on " . strftime("%Y-%m-%d %H:%M:%S") .
|
"<?php /* Smarty version %s, created on %s\n compiled from '%s' */ ?>\n",
|
||||||
"\n";
|
Smarty::SMARTY_VERSION,
|
||||||
$template_header .= " compiled from '{$this->template->source->filepath}' */ ?>\n";
|
date("Y-m-d H:i:s"),
|
||||||
|
str_replace('*/', '* /' , $this->template->source->filepath)
|
||||||
|
);
|
||||||
$code = '<?php $_smarty_tpl->smarty->ext->configLoad->_loadConfigVars($_smarty_tpl, ' .
|
$code = '<?php $_smarty_tpl->smarty->ext->configLoad->_loadConfigVars($_smarty_tpl, ' .
|
||||||
var_export($this->config_data, true) . '); ?>';
|
var_export($this->config_data, true) . '); ?>';
|
||||||
return $template_header . $this->template->smarty->ext->_codeFrame->create($this->template, $code);
|
return $template_header . $this->template->smarty->ext->_codeFrame->create($this->template, $code);
|
||||||
|
|||||||
@@ -44,9 +44,12 @@ class Smarty_Internal_Runtime_CodeFrame
|
|||||||
$properties[ 'file_dependency' ] = $_template->cached->file_dependency;
|
$properties[ 'file_dependency' ] = $_template->cached->file_dependency;
|
||||||
$properties[ 'cache_lifetime' ] = $_template->cache_lifetime;
|
$properties[ 'cache_lifetime' ] = $_template->cache_lifetime;
|
||||||
}
|
}
|
||||||
$output = "<?php\n";
|
$output = sprintf(
|
||||||
$output .= "/* Smarty version {$properties[ 'version' ]}, created on " . strftime("%Y-%m-%d %H:%M:%S") .
|
"<?php\n/* Smarty version %s, created on %s\n from '%s' */\n\n",
|
||||||
"\n from '" . str_replace('*/', '* /', $_template->source->filepath) . "' */\n\n";
|
$properties[ 'version' ],
|
||||||
|
date("Y-m-d H:i:s"),
|
||||||
|
str_replace('*/', '* /', $_template->source->filepath)
|
||||||
|
);
|
||||||
$output .= "/* @var Smarty_Internal_Template \$_smarty_tpl */\n";
|
$output .= "/* @var Smarty_Internal_Template \$_smarty_tpl */\n";
|
||||||
$dec = "\$_smarty_tpl->_decodeProperties(\$_smarty_tpl, " . var_export($properties, true) . ',' .
|
$dec = "\$_smarty_tpl->_decodeProperties(\$_smarty_tpl, " . var_export($properties, true) . ',' .
|
||||||
($cache ? 'true' : 'false') . ')';
|
($cache ? 'true' : 'false') . ')';
|
||||||
|
|||||||
@@ -29,12 +29,7 @@ class Smarty_Internal_Runtime_WriteFile
|
|||||||
{
|
{
|
||||||
$_error_reporting = error_reporting();
|
$_error_reporting = error_reporting();
|
||||||
error_reporting($_error_reporting & ~E_NOTICE & ~E_WARNING);
|
error_reporting($_error_reporting & ~E_NOTICE & ~E_WARNING);
|
||||||
$_file_perms = property_exists($smarty, '_file_perms') ? $smarty->_file_perms : 0644;
|
$old_umask = umask(0);
|
||||||
$_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);
|
$_dirpath = dirname($_filepath);
|
||||||
// if subdirs, create dir structure
|
// if subdirs, create dir structure
|
||||||
if ($_dirpath !== '.') {
|
if ($_dirpath !== '.') {
|
||||||
@@ -42,7 +37,7 @@ class Smarty_Internal_Runtime_WriteFile
|
|||||||
// loop if concurrency problem occurs
|
// loop if concurrency problem occurs
|
||||||
// see https://bugs.php.net/bug.php?id=35326
|
// see https://bugs.php.net/bug.php?id=35326
|
||||||
while (!is_dir($_dirpath)) {
|
while (!is_dir($_dirpath)) {
|
||||||
if (@mkdir($_dirpath, $_dir_perms, true)) {
|
if (@mkdir($_dirpath, 0771, true)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
clearstatcache();
|
clearstatcache();
|
||||||
@@ -89,11 +84,9 @@ class Smarty_Internal_Runtime_WriteFile
|
|||||||
error_reporting($_error_reporting);
|
error_reporting($_error_reporting);
|
||||||
throw new SmartyException("unable to write file {$_filepath}");
|
throw new SmartyException("unable to write file {$_filepath}");
|
||||||
}
|
}
|
||||||
if ($_file_perms !== null) {
|
// set file permissions
|
||||||
// set file permissions
|
chmod($_filepath, 0644);
|
||||||
chmod($_filepath, $_file_perms);
|
umask($old_umask);
|
||||||
umask($old_umask);
|
|
||||||
}
|
|
||||||
error_reporting($_error_reporting);
|
error_reporting($_error_reporting);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -422,9 +422,6 @@ abstract class Smarty_Internal_TemplateCompilerBase
|
|||||||
try {
|
try {
|
||||||
// save template object in compiler class
|
// save template object in compiler class
|
||||||
$this->template = $template;
|
$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 ($this->smarty->debugging) {
|
||||||
if (!isset($this->smarty->_debug)) {
|
if (!isset($this->smarty->_debug)) {
|
||||||
$this->smarty->_debug = new Smarty_Internal_Debug();
|
$this->smarty->_debug = new Smarty_Internal_Debug();
|
||||||
@@ -1135,7 +1132,7 @@ abstract class Smarty_Internal_TemplateCompilerBase
|
|||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
$e = new SmartyCompilerException($error_text);
|
$e = new SmartyCompilerException($error_text);
|
||||||
$e->line = $line;
|
$e->setLine($line);
|
||||||
$e->source = trim(preg_replace('![\t\r\n]+!', ' ', $match[ $line - 1 ]));
|
$e->source = trim(preg_replace('![\t\r\n]+!', ' ', $match[ $line - 1 ]));
|
||||||
$e->desc = $args;
|
$e->desc = $args;
|
||||||
$e->template = $this->template->source->filepath;
|
$e->template = $this->template->source->filepath;
|
||||||
@@ -1439,6 +1436,10 @@ abstract class Smarty_Internal_TemplateCompilerBase
|
|||||||
*/
|
*/
|
||||||
abstract protected function doCompile($_content, $isTemplateSource = false);
|
abstract protected function doCompile($_content, $isTemplateSource = false);
|
||||||
|
|
||||||
|
public function cStyleComment($string) {
|
||||||
|
return '/*' . str_replace('*/', '* /' , $string) . '*/';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile Tag
|
* Compile Tag
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -2397,6 +2397,9 @@ public static $yy_action = array(
|
|||||||
}
|
}
|
||||||
// line 749 "../smarty/lexer/smarty_internal_templateparser.y"
|
// line 749 "../smarty/lexer/smarty_internal_templateparser.y"
|
||||||
public function yy_r94(){
|
public function yy_r94(){
|
||||||
|
if ($this->security && $this->security->static_classes !== array()) {
|
||||||
|
$this->compiler->trigger_template_error('dynamic static class not allowed by security setting');
|
||||||
|
}
|
||||||
$prefixVar = $this->compiler->getNewPrefixVariable();
|
$prefixVar = $this->compiler->getNewPrefixVariable();
|
||||||
if ($this->yystack[$this->yyidx + -2]->minor['var'] === '\'smarty\'') {
|
if ($this->yystack[$this->yyidx + -2]->minor['var'] === '\'smarty\'') {
|
||||||
$this->compiler->appendPrefixCode("<?php {$prefixVar} = ". $this->compiler->compileTag('private_special_variable',array(),$this->yystack[$this->yyidx + -2]->minor['smarty_internal_index']).';?>');
|
$this->compiler->appendPrefixCode("<?php {$prefixVar} = ". $this->compiler->compileTag('private_special_variable',array(),$this->yystack[$this->yyidx + -2]->minor['smarty_internal_index']).';?>');
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ class SmartyCompilerException extends SmartyException
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The line number of the template error
|
* @param int $line
|
||||||
*
|
|
||||||
* @type int|null
|
|
||||||
*/
|
*/
|
||||||
public $line = null;
|
public function setLine($line)
|
||||||
|
{
|
||||||
|
$this->line = $line;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* The template source snippet relating to the error
|
* The template source snippet relating to the error
|
||||||
*
|
*
|
||||||
|
|||||||
Executable
+7
@@ -0,0 +1,7 @@
|
|||||||
|
# Runs tests for all supported PHP versions
|
||||||
|
docker-compose run php71 && \
|
||||||
|
docker-compose run php72 && \
|
||||||
|
docker-compose run php73 && \
|
||||||
|
docker-compose run php74 && \
|
||||||
|
docker-compose run php80 && \
|
||||||
|
docker-compose run php81
|
||||||
@@ -30,7 +30,8 @@ class CacheResourceTestCommon extends PHPUnit_Smarty
|
|||||||
|
|
||||||
public function compiledPrefilter($text, Smarty_Internal_Template $tpl)
|
public function compiledPrefilter($text, Smarty_Internal_Template $tpl)
|
||||||
{
|
{
|
||||||
return str_replace('#', $tpl->getTemplateVars('test'), $text);
|
$replace = $tpl->getTemplateVars('test');
|
||||||
|
return str_replace('#', $replace ?? '', $text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ class Smarty_Resource_Ambiguous extends Smarty_Internal_Resource_File
|
|||||||
|
|
||||||
public function __construct($directory)
|
public function __construct($directory)
|
||||||
{
|
{
|
||||||
$this->directory = rtrim($directory, "/\\") . DIRECTORY_SEPARATOR;
|
$this->directory = rtrim($directory ?? '', "/\\") . DIRECTORY_SEPARATOR;
|
||||||
// parent::__construct();
|
// parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ class ResourceStream
|
|||||||
$v = &$GLOBALS[$this->varname];
|
$v = &$GLOBALS[$this->varname];
|
||||||
$l = strlen($data);
|
$l = strlen($data);
|
||||||
$p = &$this->position;
|
$p = &$this->position;
|
||||||
$v = substr($v, 0, $p) . $data . substr($v, $p += $l);
|
$v = substr($v ?? '', 0, $p) . $data . substr($v ?? '', $p += $l);
|
||||||
|
|
||||||
return $l;
|
return $l;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,19 +257,41 @@ class SecurityTest extends PHPUnit_Smarty
|
|||||||
$this->assertEquals('25', $this->smarty->fetch($tpl));
|
$this->assertEquals('25', $this->smarty->fetch($tpl));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test not trusted PHP function
|
* test not trusted PHP function
|
||||||
* @runInSeparateProcess
|
* @runInSeparateProcess
|
||||||
* @preserveGlobalState disabled
|
* @preserveGlobalState disabled
|
||||||
*/
|
*/
|
||||||
public function testNotTrustedStaticClass()
|
public function testNotTrustedStaticClass()
|
||||||
{
|
{
|
||||||
$this->expectException('SmartyException');
|
$this->expectException('SmartyException');
|
||||||
$this->expectExceptionMessage('access to static class \'mysecuritystaticclass\' not allowed by security setting');
|
$this->expectExceptionMessage('access to static class \'mysecuritystaticclass\' not allowed by security setting');
|
||||||
$this->smarty->security_policy->static_classes = array('null');
|
$this->smarty->security_policy->static_classes = array('null');
|
||||||
$this->smarty->fetch('string:{mysecuritystaticclass::square(5)}');
|
$this->smarty->fetch('string:{mysecuritystaticclass::square(5)}');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test not trusted PHP function
|
||||||
|
*/
|
||||||
|
public function testNotTrustedStaticClassEval()
|
||||||
|
{
|
||||||
|
$this->expectException('SmartyException');
|
||||||
|
$this->expectExceptionMessage('dynamic static class not allowed by security setting');
|
||||||
|
$this->smarty->security_policy->static_classes = array('null');
|
||||||
|
$this->smarty->fetch('string:{$test = "mysecuritystaticclass"}{$test::square(5)}');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test not trusted PHP function
|
||||||
|
*/
|
||||||
|
public function testNotTrustedStaticClassSmartyVar()
|
||||||
|
{
|
||||||
|
$this->expectException('SmartyException');
|
||||||
|
$this->expectExceptionMessage('dynamic static class not allowed by security setting');
|
||||||
|
$this->smarty->security_policy->static_classes = array('null');
|
||||||
|
$this->smarty->fetch('string:{$smarty.template_object::square(5)}');
|
||||||
|
}
|
||||||
|
|
||||||
public function testChangedTrustedDirectory()
|
public function testChangedTrustedDirectory()
|
||||||
{
|
{
|
||||||
$this->smarty->security_policy->secure_dir = array(
|
$this->smarty->security_policy->secure_dir = array(
|
||||||
@@ -344,9 +366,9 @@ class SecurityTest extends PHPUnit_Smarty
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* In security mode, accessing $smarty.template_object should be illegal.
|
* In security mode, accessing $smarty.template_object should be illegal.
|
||||||
* @expectedException SmartyCompilerException
|
|
||||||
*/
|
*/
|
||||||
public function testSmartyTemplateObject() {
|
public function testSmartyTemplateObject() {
|
||||||
|
$this->expectException(SmartyCompilerException::class);
|
||||||
$this->smarty->display('string:{$smarty.template_object}');
|
$this->smarty->display('string:{$smarty.template_object}');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +416,7 @@ class ResourceStreamSecurity
|
|||||||
$v = &$GLOBALS[$this->varname];
|
$v = &$GLOBALS[$this->varname];
|
||||||
$l = strlen($data);
|
$l = strlen($data);
|
||||||
$p = &$this->position;
|
$p = &$this->position;
|
||||||
$v = substr($v, 0, $p) . $data . substr($v, $p += $l);
|
$v = substr($v ?? '', 0, $p) . $data . substr($v ?? '', $p += $l);
|
||||||
|
|
||||||
return $l;
|
return $l;
|
||||||
}
|
}
|
||||||
|
|||||||
+29
@@ -210,6 +210,7 @@ class PluginFunctionHtmlSelectDateTest extends PHPUnit_Smarty
|
|||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
$this->setUpSmarty(dirname(__FILE__));
|
$this->setUpSmarty(dirname(__FILE__));
|
||||||
|
$this->smarty->setErrorReporting(E_ALL & ~E_DEPRECATED);
|
||||||
|
|
||||||
$year = date('Y');
|
$year = date('Y');
|
||||||
$this->now = mktime(15, 0, 0, 2, 20, $year);
|
$this->now = mktime(15, 0, 0, 2, 20, $year);
|
||||||
@@ -238,6 +239,7 @@ class PluginFunctionHtmlSelectDateTest extends PHPUnit_Smarty
|
|||||||
|
|
||||||
$this->years['default'] = "<option value=\"{$year}\" selected=\"selected\">{$year}</option>";
|
$this->years['default'] = "<option value=\"{$year}\" selected=\"selected\">{$year}</option>";
|
||||||
$this->years['none'] = "<option value=\"{$year}\">{$year}</option>";
|
$this->years['none'] = "<option value=\"{$year}\">{$year}</option>";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function reverse($string)
|
protected function reverse($string)
|
||||||
@@ -394,6 +396,33 @@ class PluginFunctionHtmlSelectDateTest extends PHPUnit_Smarty
|
|||||||
$this->assertEquals($result, $tpl->fetch());
|
$this->assertEquals($result, $tpl->fetch());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testEmptyDayWithDateString() {
|
||||||
|
$n = "\n";
|
||||||
|
$result = '<select name="Date_Month">' . $n . $this->months['default'] . $n . '</select>'
|
||||||
|
. $n . '<select name="Date_Day">' . $n . '<option value="">day</option>' . $n . $this->days['none'] . $n . '</select>'
|
||||||
|
. $n . '<select name="Date_Year">' . $n . $this->years['start_2005'] . $n . '</select>';
|
||||||
|
$tpl = $this->smarty->createTemplate('eval:{html_select_date time="2022-02-" day_empty="day" start_year=2005}');
|
||||||
|
$this->assertEquals($result, $tpl->fetch());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmptyMonthWithDateStrings() {
|
||||||
|
$n = "\n";
|
||||||
|
$result = '<select name="Date_Month">' . $n . '<option value="">month</option>' . $n . $this->months['none'] . $n . '</select>'
|
||||||
|
. $n . '<select name="Date_Day">' . $n . $this->days['default'] . $n . '</select>'
|
||||||
|
. $n . '<select name="Date_Year">' . $n . $this->years['start_2005'] . $n . '</select>';
|
||||||
|
$tpl = $this->smarty->createTemplate('eval:{html_select_date time="2022--20" month_empty="month" start_year=2005}');
|
||||||
|
$this->assertEquals($result, $tpl->fetch());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmptyYearWithDateStrings() {
|
||||||
|
$n = "\n";
|
||||||
|
$result = '<select name="Date_Month">' . $n . $this->months['default'] . $n . '</select>'
|
||||||
|
. $n . '<select name="Date_Day">' . $n . $this->days['default'] . $n . '</select>'
|
||||||
|
. $n . '<select name="Date_Year">' . $n . '<option value="">year</option>' . $n . $this->years['none'] . $n . '</select>';
|
||||||
|
$tpl = $this->smarty->createTemplate('eval:{html_select_date time="-02-20" year_empty="year"}');
|
||||||
|
$this->assertEquals($result, $tpl->fetch());
|
||||||
|
}
|
||||||
|
|
||||||
public function testId()
|
public function testId()
|
||||||
{
|
{
|
||||||
$n = "\n";
|
$n = "\n";
|
||||||
|
|||||||
+19
-2
@@ -150,7 +150,7 @@ class PluginFunctionMailtoTest extends PHPUnit_Smarty
|
|||||||
|
|
||||||
public function testUmlauts()
|
public function testUmlauts()
|
||||||
{
|
{
|
||||||
$result = '<a href="mailto:me+smtpext@example.com?cc=you@example.com,they@example.com&subject=h%C3%A4llo%20w%C3%B6rld" >me+smtpext@example.com</a>';
|
$result = '<a href="mailto:me+smtpext@example.com?cc=you@example.com,they@example.com&subject=h%C3%A4llo%20w%C3%B6rld" >me+smtpext@example.com</a>';
|
||||||
$tpl = $this->smarty->createTemplate('eval:{mailto address="me+smtpext@example.com" cc="you@example.com,they@example.com" subject="hällo wörld"}');
|
$tpl = $this->smarty->createTemplate('eval:{mailto address="me+smtpext@example.com" cc="you@example.com,they@example.com" subject="hällo wörld"}');
|
||||||
$this->assertEquals(str_replace("\r", '', $result), $this->smarty->fetch($tpl));
|
$this->assertEquals(str_replace("\r", '', $result), $this->smarty->fetch($tpl));
|
||||||
}
|
}
|
||||||
@@ -158,9 +158,26 @@ class PluginFunctionMailtoTest extends PHPUnit_Smarty
|
|||||||
public function testUmlautsWithoutMbstring()
|
public function testUmlautsWithoutMbstring()
|
||||||
{
|
{
|
||||||
Smarty::$_MBSTRING = false;
|
Smarty::$_MBSTRING = false;
|
||||||
$result = '<a href="mailto:me+smtpext@example.com?cc=you@example.com,they@example.com&subject=h%C3%A4llo%20w%C3%B6rld" >me+smtpext@example.com</a>';
|
$result = '<a href="mailto:me+smtpext@example.com?cc=you@example.com,they@example.com&subject=h%C3%A4llo%20w%C3%B6rld" >me+smtpext@example.com</a>';
|
||||||
$tpl = $this->smarty->createTemplate('eval:{mailto address="me+smtpext@example.com" cc="you@example.com,they@example.com" subject="hällo wörld"}');
|
$tpl = $this->smarty->createTemplate('eval:{mailto address="me+smtpext@example.com" cc="you@example.com,they@example.com" subject="hällo wörld"}');
|
||||||
$this->assertEquals(str_replace("\r", '', $result), $this->smarty->fetch($tpl));
|
$this->assertEquals(str_replace("\r", '', $result), $this->smarty->fetch($tpl));
|
||||||
Smarty::$_MBSTRING = true;
|
Smarty::$_MBSTRING = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testJavascriptChars()
|
||||||
|
{
|
||||||
|
$result = '<script type="text/javascript">document.write(unescape(\'%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%26%71%75%6f%74%3b%26%67%74%3b%6d%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%26%23%30%33%39%3b%29%3b%20%61%6c%65%72%74%28%26%71%75%6f%74%3b%69%6e%6a%65%63%74%69%6f%6e%26%71%75%6f%74%3b%29%3b%20%2f%2f%22%20%3e%6d%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%26%71%75%6f%74%3b%26%67%74%3b%6d%65%40%65%78%61%6d%70%6c%65%2e%63%6f%6d%26%23%30%33%39%3b%29%3b%20%61%6c%65%72%74%28%26%71%75%6f%74%3b%69%6e%6a%65%63%74%69%6f%6e%26%71%75%6f%74%3b%29%3b%20%2f%2f%3c%2f%61%3e\'))</script>';
|
||||||
|
$this->smarty->assign('address', 'me@example.com">me@example.com\'); alert("injection"); //');
|
||||||
|
$tpl = $this->smarty->createTemplate('eval:{mailto address=$address encode=javascript}');
|
||||||
|
$this->assertEquals(str_replace("\r", '', $result), $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testHtmlChars()
|
||||||
|
{
|
||||||
|
$result = '<a href="mailto:me@example.com"><h1>" class="email">me@example.com"><h1></a>';
|
||||||
|
$this->smarty->assign('address', 'me@example.com"><h1>');
|
||||||
|
$tpl = $this->smarty->createTemplate('eval:{mailto address=$address extra=\'class="email"\'}');
|
||||||
|
$this->assertEquals(str_replace("\r", '', $result), $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace UnitTests\TemplateSource\TagTests\PluginModifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class for modifier tests
|
||||||
|
*
|
||||||
|
* @runTestsInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
* @backupStaticAttributes enabled
|
||||||
|
*/
|
||||||
|
class PluginModifierExplodeTest extends \PHPUnit_Smarty
|
||||||
|
{
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
* @throws \SmartyException
|
||||||
|
*
|
||||||
|
* @dataProvider explodeDataProvider
|
||||||
|
*/
|
||||||
|
public function testExplode($template, $subject, $expectedString)
|
||||||
|
{
|
||||||
|
$this->smarty->assign('subject', $subject);
|
||||||
|
|
||||||
|
$tpl = $this->smarty->createTemplate($template);
|
||||||
|
$res = $this->smarty->fetch($tpl);
|
||||||
|
|
||||||
|
$this->assertEquals($expectedString, $res);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function explodeDataProvider()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'default' => [
|
||||||
|
'template' => 'string:{","|explode:$subject|json_encode}',
|
||||||
|
'subject' => 'a,b,c,d',
|
||||||
|
'expectedString' => '["a","b","c","d"]',
|
||||||
|
],
|
||||||
|
'withNoDelimiterFound' => [
|
||||||
|
'template' => 'string:{","|explode:$subject|json_encode}',
|
||||||
|
'subject' => 'abcd',
|
||||||
|
'expectedString' => '["abcd"]',
|
||||||
|
],
|
||||||
|
'withNull' => [
|
||||||
|
'template' => 'string:{","|explode:$subject|json_encode}',
|
||||||
|
'subject' => null,
|
||||||
|
'expectedString' => '[""]',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace UnitTests\TemplateSource\TagTests\PluginModifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class for modifier tests
|
||||||
|
*
|
||||||
|
* @runTestsInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
* @backupStaticAttributes enabled
|
||||||
|
*/
|
||||||
|
class PluginModifierNumberFormatTest extends \PHPUnit_Smarty
|
||||||
|
{
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
* @throws \SmartyException
|
||||||
|
*
|
||||||
|
* @dataProvider numberFormatDataProvider
|
||||||
|
*/
|
||||||
|
public function testNumberFormat($template, $subject, $expectedString)
|
||||||
|
{
|
||||||
|
$this->smarty->assign('subject', $subject);
|
||||||
|
|
||||||
|
$tpl = $this->smarty->createTemplate($template);
|
||||||
|
|
||||||
|
$this->assertEquals($expectedString, $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function numberFormatDataProvider()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'default' => [
|
||||||
|
'template' => 'string:{$subject|number_format}',
|
||||||
|
'subject' => 12345,
|
||||||
|
'expectedString' => "12,345",
|
||||||
|
],
|
||||||
|
'withDecimalDefault' => [
|
||||||
|
'template' => 'string:{$subject|number_format}',
|
||||||
|
'subject' => 12345.6789,
|
||||||
|
'expectedString' => "12,346",
|
||||||
|
],
|
||||||
|
'withDecimalAndExtras' => [
|
||||||
|
'template' => 'string:{$subject|number_format:2:"-":"~"}',
|
||||||
|
'subject' => 12345.6789,
|
||||||
|
'expectedString' => "12~345-68",
|
||||||
|
],
|
||||||
|
'withNull' => [
|
||||||
|
'template' => 'string:{$subject|number_format}',
|
||||||
|
'subject' => null,
|
||||||
|
'expectedString' => 0,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace UnitTests\TemplateSource\TagTests\PluginModifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class for modifier tests
|
||||||
|
*
|
||||||
|
* @runTestsInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
* @backupStaticAttributes enabled
|
||||||
|
*/
|
||||||
|
class PluginModifierReplaceTest extends \PHPUnit_Smarty
|
||||||
|
{
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
* @throws \SmartyException
|
||||||
|
*
|
||||||
|
* @dataProvider replaceDataProvider
|
||||||
|
*/
|
||||||
|
public function testReplace($template, $subject, $expectedString)
|
||||||
|
{
|
||||||
|
$this->smarty->assign('subject', $subject);
|
||||||
|
|
||||||
|
$tpl = $this->smarty->createTemplate($template);
|
||||||
|
|
||||||
|
$this->assertEquals($expectedString, $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function replaceDataProvider()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'default' => [
|
||||||
|
'template' => 'string:{$subject|replace:",":"-"}',
|
||||||
|
'subject' => "a,b,c,d",
|
||||||
|
'expectedString' => "a-b-c-d",
|
||||||
|
],
|
||||||
|
'doNothing' => [
|
||||||
|
'template' => 'string:{$subject|replace:"":""}',
|
||||||
|
'subject' => "a,b,c,d",
|
||||||
|
'expectedString' => "a,b,c,d",
|
||||||
|
],
|
||||||
|
'withNull' => [
|
||||||
|
'template' => 'string:{$subject|replace:"":""}',
|
||||||
|
'subject' => null,
|
||||||
|
'expectedString' => "",
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-2
@@ -63,6 +63,11 @@ class PluginModifierUnescapeTest extends PHPUnit_Smarty
|
|||||||
$tpl = $this->smarty->createTemplate('string:{"' . $encoded . '"|unescape:"url"}');
|
$tpl = $this->smarty->createTemplate('string:{"' . $encoded . '"|unescape:"url"}');
|
||||||
$this->assertEquals($result, $this->smarty->fetch($tpl));
|
$this->assertEquals($result, $this->smarty->fetch($tpl));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
public function testCharset()
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate("string:{''Stiff Opposition Expected to Casketless Funeral Plan''|unescape:'htmlall':'utf-8'}");
|
||||||
|
$this->assertEquals("'Stiff Opposition Expected to Casketless Funeral Plan'", $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -435,9 +435,9 @@ class CompileFunctionTest extends PHPUnit_Smarty
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Test handling of function names that are a security risk
|
* Test handling of function names that are a security risk
|
||||||
* @expectedException SmartyCompilerException
|
|
||||||
*/
|
*/
|
||||||
public function testIllegalFunctionName() {
|
public function testIllegalFunctionName() {
|
||||||
|
$this->expectException(SmartyCompilerException::class);
|
||||||
$this->smarty->fetch('string:{function name=\'rce(){};echo "hi";function \'}{/function}');
|
$this->smarty->fetch('string:{function name=\'rce(){};echo "hi";function \'}{/function}');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,30 @@ class MathTest extends PHPUnit_Smarty
|
|||||||
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testMultipleOperators()
|
||||||
|
{
|
||||||
|
$this->smarty->disableSecurity();
|
||||||
|
$expected = "2 -- 2";
|
||||||
|
$tpl = $this->smarty->createTemplate('eval:{$x = 5}{$y = 4}{math equation="x - y + 1" x=$x y=$y} -- {math equation="5 - 4 + 1"}');
|
||||||
|
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMathMaxFunctionParameters()
|
||||||
|
{
|
||||||
|
$this->smarty->disableSecurity();
|
||||||
|
$expected = max(0, 2) . ' -- ' . max(0, 2, 3);
|
||||||
|
$tpl = $this->smarty->createTemplate('eval:{$x = 0}{$y = 2}{$z = 3}{math equation="max(x, y)" x=$x y=$y} -- {math equation="max(x, y, z)" x=$x y=$y z=$z}');
|
||||||
|
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMathMinFunctionParameters()
|
||||||
|
{
|
||||||
|
$this->smarty->disableSecurity();
|
||||||
|
$expected = min(1, 2) . ' -- ' . min(1, 2, 0);
|
||||||
|
$tpl = $this->smarty->createTemplate('eval:{$x = 1}{$y = 2}{$z = 0}{math equation="min(x, y)" x=$x y=$y} -- {math equation="min(x, y, z)" x=$x y=$y z=$z}');
|
||||||
|
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
public function testSyntaxSin()
|
public function testSyntaxSin()
|
||||||
{
|
{
|
||||||
$this->smarty->disableSecurity();
|
$this->smarty->disableSecurity();
|
||||||
@@ -108,34 +132,36 @@ class MathTest extends PHPUnit_Smarty
|
|||||||
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException PHPUnit_Framework_Error_Warning
|
|
||||||
*/
|
|
||||||
public function testBackticksIllegal()
|
public function testBackticksIllegal()
|
||||||
{
|
{
|
||||||
|
$this->expectException(PHPUnit\Framework\Error\Warning::class);
|
||||||
$expected = "22.00";
|
$expected = "22.00";
|
||||||
$tpl = $this->smarty->createTemplate('eval:{$x = "4"}{$y = "5.5"}{math equation="`ls` x * y" x=$x y=$y}');
|
$tpl = $this->smarty->createTemplate('eval:{$x = "4"}{$y = "5.5"}{math equation="`ls` x * y" x=$x y=$y}');
|
||||||
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException PHPUnit_Framework_Error_Warning
|
|
||||||
*/
|
|
||||||
public function testDollarSignsIllegal()
|
public function testDollarSignsIllegal()
|
||||||
{
|
{
|
||||||
|
$this->expectException(PHPUnit\Framework\Error\Warning::class);
|
||||||
$expected = "22.00";
|
$expected = "22.00";
|
||||||
$tpl = $this->smarty->createTemplate('eval:{$x = "4"}{$y = "5.5"}{math equation="$" x=$x y=$y}');
|
$tpl = $this->smarty->createTemplate('eval:{$x = "4"}{$y = "5.5"}{math equation="$" x=$x y=$y}');
|
||||||
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException PHPUnit_Framework_Error_Warning
|
|
||||||
*/
|
|
||||||
public function testBracketsIllegal()
|
public function testBracketsIllegal()
|
||||||
{
|
{
|
||||||
|
$this->expectException(PHPUnit\Framework\Error\Warning::class);
|
||||||
$expected = "I";
|
$expected = "I";
|
||||||
$tpl = $this->smarty->createTemplate('eval:{$x = "0"}{$y = "1"}{math equation="((y/x).(x))[x]" x=$x y=$y}');
|
$tpl = $this->smarty->createTemplate('eval:{$x = "0"}{$y = "1"}{math equation="((y/x).(x))[x]" x=$x y=$y}');
|
||||||
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
$this->assertEquals($expected, $this->smarty->fetch($tpl));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testRand()
|
||||||
|
{
|
||||||
|
$tpl = $this->smarty->createTemplate('eval:{$x = "0"}{math equation="x * rand()" x=$x}');
|
||||||
|
// this assertion may seem silly, but it serves to prove that using rand() without a parameter
|
||||||
|
// will not trigger a security error (see https://github.com/smarty-php/smarty/issues/794)
|
||||||
|
$this->assertEquals("0", $this->smarty->fetch($tpl));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ class VariableStream
|
|||||||
$v = &$GLOBALS[$this->varname];
|
$v = &$GLOBALS[$this->varname];
|
||||||
$l = strlen($data);
|
$l = strlen($data);
|
||||||
$p = &$this->position;
|
$p = &$this->position;
|
||||||
$v = substr($v, 0, $p) . $data . substr($v, $p += $l);
|
$v = substr($v ?? '', 0, $p) . $data . substr($v ?? '', $p += $l);
|
||||||
|
|
||||||
return $l;
|
return $l;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Smarty PHPunit tests - issue #549 regression tests
|
||||||
|
*
|
||||||
|
* @package PHPunit
|
||||||
|
* @author Andrey Repin <anrdaemon@yandex.ru>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class for compiler tests
|
||||||
|
*
|
||||||
|
* @runTestsInSeparateProcess
|
||||||
|
* @preserveGlobalState disabled
|
||||||
|
* @backupStaticAttributes enabled
|
||||||
|
*
|
||||||
|
* mb_split breaks if Smarty encoding is not the same as mbstring regex encoding.
|
||||||
|
*/
|
||||||
|
class MbSplitEncodingIssue549Test extends PHPUnit_Smarty
|
||||||
|
{
|
||||||
|
/** @var string Saved Smarty charset */
|
||||||
|
private $charset;
|
||||||
|
|
||||||
|
/** @var array Source data for tests, hexed to protect from accidental reencoding */
|
||||||
|
private $data = array(
|
||||||
|
"subject" => '4772c3bc6e6577616c64', // "Grünewald"
|
||||||
|
"pattern" => '77616c64', // "wald"
|
||||||
|
"replacement" => '7374c3bc726d', // "stürm"
|
||||||
|
"result" => '4772c3bc6e657374c3bc726d', // "Grünestürm"
|
||||||
|
);
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
if(!\Smarty::$_MBSTRING)
|
||||||
|
{
|
||||||
|
$this->markTestSkipped("mbstring extension is not in use by Smarty");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->charset = \Smarty::$_CHARSET;
|
||||||
|
$this->setUpSmarty(dirname(__FILE__));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function tearDown(): void
|
||||||
|
{
|
||||||
|
\Smarty::$_CHARSET = $this->charset ?: \Smarty::$_CHARSET;
|
||||||
|
$this->cleanDirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Provider for testReplaceModifier
|
||||||
|
*/
|
||||||
|
public function encodingPairsProvider()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
"with non-UNICODE src/non-UNICODE regex (PHP < 5.6 default)" => array("Windows-1252", "EUC-JP"),
|
||||||
|
"with UTF-8 src/non-UNICODE regex (PHP < 5.6 default)" => array("UTF-8", "EUC-JP"),
|
||||||
|
"with UTF-8 src/UTF-8 regex (PHP >= 5.6)" => array("UTF-8", "UTF-8"),
|
||||||
|
"with non-UNICODE src/UTF-8 regex" => array("Windows-1252", "UTF-8"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Test behavior of `replace` modifier with different source and regex encodings
|
||||||
|
*
|
||||||
|
* @dataProvider encodingPairsProvider
|
||||||
|
*/
|
||||||
|
public function testReplaceModifier($mb_int_encoding, $mb_regex_encoding)
|
||||||
|
{
|
||||||
|
$data = $this->data;
|
||||||
|
\array_walk($data, function(&$value, $key) use($mb_int_encoding) {
|
||||||
|
$value = \mb_convert_encoding(pack("H*", $value), $mb_int_encoding, "UTF-8");
|
||||||
|
});
|
||||||
|
\extract($data, \EXTR_SKIP);
|
||||||
|
|
||||||
|
\mb_regex_encoding($mb_regex_encoding);
|
||||||
|
\Smarty::$_CHARSET = $mb_int_encoding;
|
||||||
|
$this->assertEquals($result, $this->smarty->fetch("string:{\"$subject\"|replace:\"$pattern\":\"$replacement\"}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# Ignore anything in here, but keep this directory
|
||||||
|
*
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
# Ignore anything in here, but keep this directory
|
||||||
|
*
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
FROM php:7.1-cli
|
||||||
|
|
||||||
|
## Basic utilities
|
||||||
|
RUN apt-get update -yqq && apt-get install -y curl apt-utils git zip unzip
|
||||||
|
|
||||||
|
## Composer
|
||||||
|
COPY ./utilities/testrunners/shared/install-composer.sh /root/install-composer.sh
|
||||||
|
WORKDIR /root
|
||||||
|
RUN sh ./install-composer.sh
|
||||||
|
RUN mv ./composer.phar /usr/local/bin/composer
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
FROM php:7.2-cli
|
||||||
|
|
||||||
|
## Basic utilities
|
||||||
|
RUN apt-get update -yqq && apt-get install -y curl apt-utils git zip unzip
|
||||||
|
|
||||||
|
## Composer
|
||||||
|
COPY ./utilities/testrunners/shared/install-composer.sh /root/install-composer.sh
|
||||||
|
WORKDIR /root
|
||||||
|
RUN sh ./install-composer.sh
|
||||||
|
RUN mv ./composer.phar /usr/local/bin/composer
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
FROM php:7.3-cli
|
||||||
|
|
||||||
|
## Basic utilities
|
||||||
|
RUN apt-get update -yqq && apt-get install -y curl apt-utils git zip unzip
|
||||||
|
|
||||||
|
## Composer
|
||||||
|
COPY ./utilities/testrunners/shared/install-composer.sh /root/install-composer.sh
|
||||||
|
WORKDIR /root
|
||||||
|
RUN sh ./install-composer.sh
|
||||||
|
RUN mv ./composer.phar /usr/local/bin/composer
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
FROM php:7.4-cli
|
||||||
|
|
||||||
|
## Basic utilities
|
||||||
|
RUN apt-get update -yqq && apt-get install -y curl apt-utils git zip unzip
|
||||||
|
|
||||||
|
## Composer
|
||||||
|
COPY ./utilities/testrunners/shared/install-composer.sh /root/install-composer.sh
|
||||||
|
WORKDIR /root
|
||||||
|
RUN sh ./install-composer.sh
|
||||||
|
RUN mv ./composer.phar /usr/local/bin/composer
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
FROM php:8.0-cli
|
||||||
|
|
||||||
|
## Basic utilities
|
||||||
|
RUN apt-get update -yqq && apt-get install -y curl apt-utils git zip unzip
|
||||||
|
|
||||||
|
## Composer
|
||||||
|
COPY ./utilities/testrunners/shared/install-composer.sh /root/install-composer.sh
|
||||||
|
WORKDIR /root
|
||||||
|
RUN sh ./install-composer.sh
|
||||||
|
RUN mv ./composer.phar /usr/local/bin/composer
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
FROM php:8.1-cli
|
||||||
|
|
||||||
|
## Basic utilities
|
||||||
|
RUN apt-get update -yqq && apt-get install -y curl apt-utils git zip unzip
|
||||||
|
|
||||||
|
## Composer
|
||||||
|
COPY ./utilities/testrunners/shared/install-composer.sh /root/install-composer.sh
|
||||||
|
WORKDIR /root
|
||||||
|
RUN sh ./install-composer.sh
|
||||||
|
RUN mv ./composer.phar /usr/local/bin/composer
|
||||||
Executable
+2
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
composer update && php ./vendor/phpunit/phpunit/phpunit
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')"
|
||||||
|
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
|
||||||
|
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"
|
||||||
|
|
||||||
|
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
|
||||||
|
then
|
||||||
|
>&2 echo 'ERROR: Invalid installer checksum'
|
||||||
|
rm composer-setup.php
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
php composer-setup.php --quiet
|
||||||
|
RESULT=$?
|
||||||
|
rm composer-setup.php
|
||||||
|
exit $RESULT
|
||||||
Reference in New Issue
Block a user