From eabe70ea086b9e9471d563bea5ab718615ee537a Mon Sep 17 00:00:00 2001 From: Simon Wisselink Date: Sat, 6 Apr 2024 23:37:50 +0200 Subject: [PATCH] Fixed unit tests to not rely on the existence of any domain or unavailability of internet access when running tests. --- src/BlockHandler/TextFormat.php | 3 - src/Compile/Modifier/CatModifierCompiler.php | 2 - .../CountCharactersModifierCompiler.php | 2 - .../CountParagraphsModifierCompiler.php | 2 - .../CountSentencesModifierCompiler.php | 2 - .../Modifier/CountWordsModifierCompiler.php | 1 - .../Modifier/DefaultModifierCompiler.php | 1 - .../Modifier/EscapeModifierCompiler.php | 1 - .../Modifier/IndentModifierCompiler.php | 1 - .../Modifier/LowerModifierCompiler.php | 1 - .../Modifier/Nl2brModifierCompiler.php | 1 - .../Modifier/RoundModifierCompiler.php | 1 - .../Modifier/StrRepeatModifierCompiler.php | 1 - .../Modifier/StringFormatModifierCompiler.php | 1 - .../Modifier/StripModifierCompiler.php | 1 - .../Modifier/StripTagsModifierCompiler.php | 1 - .../Modifier/StrlenModifierCompiler.php | 1 - .../Modifier/UpperModifierCompiler.php | 1 - .../Modifier/WordWrapModifierCompiler.php | 1 - src/Data.php | 8 - src/Extension/DefaultExtension.php | 7 - src/FunctionHandler/Counter.php | 2 - src/FunctionHandler/Cycle.php | 2 - src/FunctionHandler/Fetch.php | 2 - src/FunctionHandler/HtmlCheckboxes.php | 2 - src/FunctionHandler/HtmlImage.php | 2 - src/FunctionHandler/HtmlOptions.php | 2 - src/FunctionHandler/HtmlRadios.php | 2 - src/FunctionHandler/HtmlSelectDate.php | 2 - src/FunctionHandler/HtmlSelectTime.php | 2 - src/FunctionHandler/HtmlTable.php | 2 - src/FunctionHandler/Mailto.php | 2 - src/FunctionHandler/Math.php | 2 - src/Smarty.php | 15 - src/Template.php | 1 - src/TemplateBase.php | 7 - .../UnitTests/SecurityTests/SecurityTest.php | 786 +++++++++--------- .../PluginFunctionFetchTest.php | 132 ++- .../TagTests/PluginFunction/testfile.txt | 1 + 39 files changed, 453 insertions(+), 553 deletions(-) create mode 100644 tests/UnitTests/TemplateSource/TagTests/PluginFunction/testfile.txt diff --git a/src/BlockHandler/TextFormat.php b/src/BlockHandler/TextFormat.php index 9cd804bb1..b4fa5acd4 100644 --- a/src/BlockHandler/TextFormat.php +++ b/src/BlockHandler/TextFormat.php @@ -20,9 +20,6 @@ * - indent_char - string (" ") * - wrap_boundary - boolean (true) * - * @link https://www.smarty.net/manual/en/language.function.textformat.php {textformat} - * (Smarty online manual) - * * @param array $params parameters * @param string $content contents of the block * @param Template $template template object diff --git a/src/Compile/Modifier/CatModifierCompiler.php b/src/Compile/Modifier/CatModifierCompiler.php index f7cc2589f..21005d5be 100644 --- a/src/Compile/Modifier/CatModifierCompiler.php +++ b/src/Compile/Modifier/CatModifierCompiler.php @@ -11,8 +11,6 @@ * Input: string to catenate * Example: {$var|cat:"foo"} * - * @link https://www.smarty.net/manual/en/language.modifier.cat.php cat - * (Smarty online manual) * @author Uwe Tews */ diff --git a/src/Compile/Modifier/CountCharactersModifierCompiler.php b/src/Compile/Modifier/CountCharactersModifierCompiler.php index 0afad80b9..fb5f5ca33 100644 --- a/src/Compile/Modifier/CountCharactersModifierCompiler.php +++ b/src/Compile/Modifier/CountCharactersModifierCompiler.php @@ -6,8 +6,6 @@ * Name: count_characters * Purpose: count the number of characters in a text * - * @link https://www.smarty.net/manual/en/language.modifier.count.characters.php count_characters (Smarty online - * manual) * @author Uwe Tews */ diff --git a/src/Compile/Modifier/CountParagraphsModifierCompiler.php b/src/Compile/Modifier/CountParagraphsModifierCompiler.php index f67e64a35..76552e073 100644 --- a/src/Compile/Modifier/CountParagraphsModifierCompiler.php +++ b/src/Compile/Modifier/CountParagraphsModifierCompiler.php @@ -6,8 +6,6 @@ * Name: count_paragraphs * Purpose: count the number of paragraphs in a text * - * @link https://www.smarty.net/manual/en/language.modifier.count.paragraphs.php - * count_paragraphs (Smarty online manual) * @author Uwe Tews */ diff --git a/src/Compile/Modifier/CountSentencesModifierCompiler.php b/src/Compile/Modifier/CountSentencesModifierCompiler.php index 503d63f18..bc7c43e1c 100644 --- a/src/Compile/Modifier/CountSentencesModifierCompiler.php +++ b/src/Compile/Modifier/CountSentencesModifierCompiler.php @@ -6,8 +6,6 @@ * Name: count_sentences * Purpose: count the number of sentences in a text * - * @link https://www.smarty.net/manual/en/language.modifier.count.paragraphs.php - * count_sentences (Smarty online manual) * @author Uwe Tews */ diff --git a/src/Compile/Modifier/CountWordsModifierCompiler.php b/src/Compile/Modifier/CountWordsModifierCompiler.php index e1c648ab1..c11d546d4 100644 --- a/src/Compile/Modifier/CountWordsModifierCompiler.php +++ b/src/Compile/Modifier/CountWordsModifierCompiler.php @@ -6,7 +6,6 @@ * Name: count_words * Purpose: count the number of words in a text * - * @link https://www.smarty.net/manual/en/language.modifier.count.words.php count_words (Smarty online manual) * @author Uwe Tews */ diff --git a/src/Compile/Modifier/DefaultModifierCompiler.php b/src/Compile/Modifier/DefaultModifierCompiler.php index f802e4d55..3d82aa70c 100644 --- a/src/Compile/Modifier/DefaultModifierCompiler.php +++ b/src/Compile/Modifier/DefaultModifierCompiler.php @@ -6,7 +6,6 @@ * Name: default * Purpose: designate default value for empty variables * - * @link https://www.smarty.net/manual/en/language.modifier.default.php default (Smarty online manual) * @author Uwe Tews */ diff --git a/src/Compile/Modifier/EscapeModifierCompiler.php b/src/Compile/Modifier/EscapeModifierCompiler.php index 54e6f34b8..b600e08c8 100644 --- a/src/Compile/Modifier/EscapeModifierCompiler.php +++ b/src/Compile/Modifier/EscapeModifierCompiler.php @@ -9,7 +9,6 @@ * Name: escape * Purpose: escape string for output * - * @link https://www.smarty.net/docsv2/en/language.modifier.escape count_characters (Smarty online manual) * @author Rodney Rehm */ diff --git a/src/Compile/Modifier/IndentModifierCompiler.php b/src/Compile/Modifier/IndentModifierCompiler.php index 401e24a1a..353e757f0 100644 --- a/src/Compile/Modifier/IndentModifierCompiler.php +++ b/src/Compile/Modifier/IndentModifierCompiler.php @@ -6,7 +6,6 @@ * Name: indent * Purpose: indent lines of text * - * @link https://www.smarty.net/manual/en/language.modifier.indent.php indent (Smarty online manual) * @author Uwe Tews */ diff --git a/src/Compile/Modifier/LowerModifierCompiler.php b/src/Compile/Modifier/LowerModifierCompiler.php index 4186b1ec7..62fc87e90 100644 --- a/src/Compile/Modifier/LowerModifierCompiler.php +++ b/src/Compile/Modifier/LowerModifierCompiler.php @@ -6,7 +6,6 @@ * Name: lower * Purpose: convert string to lowercase * - * @link https://www.smarty.net/manual/en/language.modifier.lower.php lower (Smarty online manual) * @author Monte Ohrt * @author Uwe Tews */ diff --git a/src/Compile/Modifier/Nl2brModifierCompiler.php b/src/Compile/Modifier/Nl2brModifierCompiler.php index 074e6772e..c3b1aa533 100644 --- a/src/Compile/Modifier/Nl2brModifierCompiler.php +++ b/src/Compile/Modifier/Nl2brModifierCompiler.php @@ -7,7 +7,6 @@ * Name: nl2br * Purpose: insert HTML line breaks before all newlines in a string * - * @link https://www.smarty.net/docs/en/language.modifier.nl2br.tpl nl2br (Smarty online manual) */ class Nl2brModifierCompiler extends Base { diff --git a/src/Compile/Modifier/RoundModifierCompiler.php b/src/Compile/Modifier/RoundModifierCompiler.php index 33645ea0b..82476833e 100644 --- a/src/Compile/Modifier/RoundModifierCompiler.php +++ b/src/Compile/Modifier/RoundModifierCompiler.php @@ -7,7 +7,6 @@ * Name: round * Purpose: Returns the rounded value of num to specified precision (number of digits after the decimal point) * - * @link https://www.smarty.net/docs/en/language.modifier.round.tpl round (Smarty online manual) */ class RoundModifierCompiler extends Base { diff --git a/src/Compile/Modifier/StrRepeatModifierCompiler.php b/src/Compile/Modifier/StrRepeatModifierCompiler.php index dbe4ba779..c33af3299 100644 --- a/src/Compile/Modifier/StrRepeatModifierCompiler.php +++ b/src/Compile/Modifier/StrRepeatModifierCompiler.php @@ -6,7 +6,6 @@ * Name: str_repeat * Purpose: returns string repeated times times * - * @link https://www.smarty.net/docs/en/language.modifier.str_repeat.tpl str_repeat (Smarty online manual) */ class StrRepeatModifierCompiler extends Base { diff --git a/src/Compile/Modifier/StringFormatModifierCompiler.php b/src/Compile/Modifier/StringFormatModifierCompiler.php index a0c23ae52..e662f0164 100644 --- a/src/Compile/Modifier/StringFormatModifierCompiler.php +++ b/src/Compile/Modifier/StringFormatModifierCompiler.php @@ -6,7 +6,6 @@ * Name: string_format * Purpose: format strings via sprintf * - * @link https://www.smarty.net/manual/en/language.modifier.string.format.php string_format (Smarty online manual) * @author Uwe Tews */ diff --git a/src/Compile/Modifier/StripModifierCompiler.php b/src/Compile/Modifier/StripModifierCompiler.php index 788716400..d85f83df3 100644 --- a/src/Compile/Modifier/StripModifierCompiler.php +++ b/src/Compile/Modifier/StripModifierCompiler.php @@ -9,7 +9,6 @@ * Example: {$var|strip} {$var|strip:" "} * Date: September 25th, 2002 * - * @link https://www.smarty.net/manual/en/language.modifier.strip.php strip (Smarty online manual) * @author Uwe Tews */ diff --git a/src/Compile/Modifier/StripTagsModifierCompiler.php b/src/Compile/Modifier/StripTagsModifierCompiler.php index e8885bc79..dfd09437a 100644 --- a/src/Compile/Modifier/StripTagsModifierCompiler.php +++ b/src/Compile/Modifier/StripTagsModifierCompiler.php @@ -6,7 +6,6 @@ * Name: strip_tags * Purpose: strip html tags from text * - * @link https://www.smarty.net/docs/en/language.modifier.strip.tags.tpl strip_tags (Smarty online manual) * @author Uwe Tews */ diff --git a/src/Compile/Modifier/StrlenModifierCompiler.php b/src/Compile/Modifier/StrlenModifierCompiler.php index 07a44718b..5cc666fd5 100644 --- a/src/Compile/Modifier/StrlenModifierCompiler.php +++ b/src/Compile/Modifier/StrlenModifierCompiler.php @@ -7,7 +7,6 @@ * Name: strlen * Purpose: return the length of the given string * - * @link https://www.smarty.net/docs/en/language.modifier.strlen.tpl strlen (Smarty online manual) */ class StrlenModifierCompiler extends Base { diff --git a/src/Compile/Modifier/UpperModifierCompiler.php b/src/Compile/Modifier/UpperModifierCompiler.php index 9bef41ffd..74e9a7024 100644 --- a/src/Compile/Modifier/UpperModifierCompiler.php +++ b/src/Compile/Modifier/UpperModifierCompiler.php @@ -6,7 +6,6 @@ * Name: lower * Purpose: convert string to uppercase * - * @link https://www.smarty.net/manual/en/language.modifier.upper.php lower (Smarty online manual) * @author Uwe Tews */ diff --git a/src/Compile/Modifier/WordWrapModifierCompiler.php b/src/Compile/Modifier/WordWrapModifierCompiler.php index 4a6d84b09..092b95a80 100644 --- a/src/Compile/Modifier/WordWrapModifierCompiler.php +++ b/src/Compile/Modifier/WordWrapModifierCompiler.php @@ -6,7 +6,6 @@ * Name: wordwrap * Purpose: wrap a string of text at a given length * - * @link https://www.smarty.net/manual/en/language.modifier.wordwrap.php wordwrap (Smarty online manual) * @author Uwe Tews */ diff --git a/src/Data.php b/src/Data.php index 582ee6601..64a4770ec 100644 --- a/src/Data.php +++ b/src/Data.php @@ -163,8 +163,6 @@ public function assign($tpl_var, $value = null, $nocache = false, $scope = null) * be not cached * * @return Data - * @link https://www.smarty.net/docs/en/api.append.tpl - * * @api Smarty::append() */ public function append($tpl_var, $value = null, $merge = false, $nocache = false) @@ -218,7 +216,6 @@ public function assignGlobal($varName, $value = null, $nocache = false) * * @return mixed variable value or or array of variables * @api Smarty::getTemplateVars() - * @link https://www.smarty.net/docs/en/api.get.template.vars.tpl * */ public function getTemplateVars($varName = null, $searchParents = true) @@ -351,7 +348,6 @@ public function getSmarty() * @param string|array $tpl_var the template variable(s) to clear * * @return Data - * @link https://www.smarty.net/docs/en/api.clear.assign.tpl * * @api Smarty::clearAssign() */ @@ -371,7 +367,6 @@ public function clearAssign($tpl_var) * clear all the assigned template variables. * * @return Data - * @link https://www.smarty.net/docs/en/api.clear.all.assign.tpl * * @api Smarty::clearAllAssign() */ @@ -387,7 +382,6 @@ public function clearAllAssign() * @param string|null $name variable name or null * * @return Data - * @link https://www.smarty.net/docs/en/api.clear.config.tpl * * @api Smarty::clearConfig() */ @@ -440,7 +434,6 @@ public function hasConfigVariable($varName): bool { * * @return mixed variable value or or array of variables * @throws Exception - * @link https://www.smarty.net/docs/en/api.get.config.vars.tpl * * @api Smarty::getConfigVars() */ @@ -462,7 +455,6 @@ public function getConfigVars($varname = null) * @returns $this * @throws \Exception - * @link https://www.smarty.net/docs/en/api.config.load.tpl * * @api Smarty::configLoad() */ diff --git a/src/Extension/DefaultExtension.php b/src/Extension/DefaultExtension.php index e400dddbb..cecc4a46f 100644 --- a/src/Extension/DefaultExtension.php +++ b/src/Extension/DefaultExtension.php @@ -113,7 +113,6 @@ public function getBlockHandler(string $blockTagName): ?\Smarty\BlockHandler\Blo * Name: spacify * Purpose: add spaces between characters in a string * - * @link https://www.smarty.net/manual/en/language.modifier.spacify.php spacify (Smarty online manual) * @author Monte Ohrt * * @param string $string input string @@ -234,7 +233,6 @@ public function smarty_modifier_count($arrayOrObject, $mode = 0) { * - format: strftime format for output * - default_date: default date if $string is empty * - * @link https://www.smarty.net/manual/en/language.modifier.date.format.php date_format (Smarty online manual) * @author Monte Ohrt * * @param string $string input date string @@ -386,7 +384,6 @@ public function smarty_modifier_debug_print_var($var, $max = 10, $length = 40, $ * Name: escape * Purpose: escape string for output * - * @link https://www.smarty.net/docs/en/language.modifier.escape * @author Monte Ohrt * * @param string $string input string @@ -654,8 +651,6 @@ public function smarty_modifier_number_format(?float $num, int $decimals = 0, ?s * Name: regex_replace * Purpose: regular expression search/replace * - * @link https://www.smarty.net/manual/en/language.modifier.regex.replace.php - * regex_replace (Smarty online manual) * @author Monte Ohrt * * @param string $string input string @@ -703,7 +698,6 @@ private function regex_replace_check($search) * Name: replace * Purpose: simple search/replace * - * @link https://www.smarty.net/manual/en/language.modifier.replace.php replace (Smarty online manual) * @author Monte Ohrt * @author Uwe Tews * @@ -726,7 +720,6 @@ public function smarty_modifier_replace($string, $search, $replace) * optionally splitting in the middle of a word, and * appending the $etc string or inserting $etc into the middle. * - * @link https://www.smarty.net/manual/en/language.modifier.truncate.php truncate (Smarty online manual) * @author Monte Ohrt * * @param string $string input string diff --git a/src/FunctionHandler/Counter.php b/src/FunctionHandler/Counter.php index c6f9fdbe4..b447caf1f 100644 --- a/src/FunctionHandler/Counter.php +++ b/src/FunctionHandler/Counter.php @@ -13,8 +13,6 @@ * @param Template $template template object * * @return string|null - *@link https://www.smarty.net/manual/en/language.function.counter.php {counter} - * (Smarty online manual) * * @author Monte Ohrt */ diff --git a/src/FunctionHandler/Cycle.php b/src/FunctionHandler/Cycle.php index 756573fac..909a688b6 100644 --- a/src/FunctionHandler/Cycle.php +++ b/src/FunctionHandler/Cycle.php @@ -26,8 +26,6 @@ * {cycle name=row values="one,two,three" reset=true} * {cycle name=row} * - * @link https://www.smarty.net/manual/en/language.function.cycle.php {cycle} - * (Smarty online manual) * @author Monte Ohrt * @author credit to Mark Priatel * @author credit to Gerard diff --git a/src/FunctionHandler/Fetch.php b/src/FunctionHandler/Fetch.php index 3031ac88c..d10ef668f 100644 --- a/src/FunctionHandler/Fetch.php +++ b/src/FunctionHandler/Fetch.php @@ -10,8 +10,6 @@ * Name: fetch * Purpose: fetch file, web or ftp data and display results * - * @link https://www.smarty.net/manual/en/language.function.fetch.php {fetch} - * (Smarty online manual) * @author Monte Ohrt * * @param array $params parameters diff --git a/src/FunctionHandler/HtmlCheckboxes.php b/src/FunctionHandler/HtmlCheckboxes.php index a32b48b26..45ecc40a1 100644 --- a/src/FunctionHandler/HtmlCheckboxes.php +++ b/src/FunctionHandler/HtmlCheckboxes.php @@ -27,8 +27,6 @@ * - assign (optional) - assign the output as an array to this variable * - escape (optional) - escape the content (not value), defaults to true * - * @link https://www.smarty.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} - * (Smarty online manual) * @author Christopher Kvarme * @author credits to Monte Ohrt * @version 1.0 diff --git a/src/FunctionHandler/HtmlImage.php b/src/FunctionHandler/HtmlImage.php index a524eef94..9cb087456 100644 --- a/src/FunctionHandler/HtmlImage.php +++ b/src/FunctionHandler/HtmlImage.php @@ -20,8 +20,6 @@ * - basedir - (optional) - base directory for absolute paths, default is environment variable DOCUMENT_ROOT * - path_prefix - prefix for path output (optional, default empty) * - * @link https://www.smarty.net/manual/en/language.function.html.image.php {html_image} - * (Smarty online manual) * @author Monte Ohrt * @author credits to Duda * @version 1.0 diff --git a/src/FunctionHandler/HtmlOptions.php b/src/FunctionHandler/HtmlOptions.php index c008766db..5346738b6 100644 --- a/src/FunctionHandler/HtmlOptions.php +++ b/src/FunctionHandler/HtmlOptions.php @@ -19,8 +19,6 @@ * - id (optional) - string default not set * - class (optional) - string default not set * - * @link https://www.smarty.net/manual/en/language.function.html.options.php {html_image} - * (Smarty online manual) * @author Monte Ohrt * @author Ralf Strehle (minor optimization) * diff --git a/src/FunctionHandler/HtmlRadios.php b/src/FunctionHandler/HtmlRadios.php index 0cc95609a..544c5c7d4 100644 --- a/src/FunctionHandler/HtmlRadios.php +++ b/src/FunctionHandler/HtmlRadios.php @@ -27,8 +27,6 @@ * {html_radios values=$ids name='box' separator='
' output=$names} * {html_radios values=$ids checked=$checked separator='
' output=$names} * - * @link https://www.smarty.net/manual/en/language.function.html.radios.php {html_radios} - * (Smarty online manual) * @author Christopher Kvarme * @author credits to Monte Ohrt * @version 1.0 diff --git a/src/FunctionHandler/HtmlSelectDate.php b/src/FunctionHandler/HtmlSelectDate.php index 55e36641d..a6acfb7bd 100644 --- a/src/FunctionHandler/HtmlSelectDate.php +++ b/src/FunctionHandler/HtmlSelectDate.php @@ -26,8 +26,6 @@ * - 2.0 complete rewrite for performance, * added attributes month_names, *_id * - * @link https://www.smarty.net/manual/en/language.function.html.select.date.php {html_select_date} - * (Smarty online manual) * @version 2.0 * @author Andrei Zmievski * @author Monte Ohrt diff --git a/src/FunctionHandler/HtmlSelectTime.php b/src/FunctionHandler/HtmlSelectTime.php index 6e4f679df..40679c10c 100644 --- a/src/FunctionHandler/HtmlSelectTime.php +++ b/src/FunctionHandler/HtmlSelectTime.php @@ -9,8 +9,6 @@ * Name: html_select_time * Purpose: Prints the dropdowns for time selection * - * @link https://www.smarty.net/manual/en/language.function.html.select.time.php {html_select_time} - * (Smarty online manual) * @author Roberto Berto * @author Monte Ohrt * diff --git a/src/FunctionHandler/HtmlTable.php b/src/FunctionHandler/HtmlTable.php index 1dadc7f1d..d5d147053 100644 --- a/src/FunctionHandler/HtmlTable.php +++ b/src/FunctionHandler/HtmlTable.php @@ -37,8 +37,6 @@ * @return string *@author credit to boots * @version 1.1 - * @link https://www.smarty.net/manual/en/language.function.html.table.php {html_table} - * (Smarty online manual) * * @author Monte Ohrt * @author credit to Messju Mohr diff --git a/src/FunctionHandler/Mailto.php b/src/FunctionHandler/Mailto.php index 8f7b821a5..eb35c48eb 100644 --- a/src/FunctionHandler/Mailto.php +++ b/src/FunctionHandler/Mailto.php @@ -35,8 +35,6 @@ * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"} * {mailto address="me@domain.com" extra='class="mailto"'} * - * @link https://www.smarty.net/manual/en/language.function.mailto.php {mailto} - * (Smarty online manual) * @version 1.2 * @author Monte Ohrt * @author credits to Jason Sweat (added cc, bcc and subject functionality) diff --git a/src/FunctionHandler/Math.php b/src/FunctionHandler/Math.php index f8236ca9a..23ef9253d 100644 --- a/src/FunctionHandler/Math.php +++ b/src/FunctionHandler/Math.php @@ -10,8 +10,6 @@ * Name: math * Purpose: handle math computations in template * - * @link https://www.smarty.net/manual/en/language.function.math.php {math} - * (Smarty online manual) * @author Monte Ohrt * * @param array $params parameters diff --git a/src/Smarty.php b/src/Smarty.php index bf1d3fad5..18ff52624 100644 --- a/src/Smarty.php +++ b/src/Smarty.php @@ -40,7 +40,6 @@ * Smarty mailing list. Send a blank e-mail to * smarty-discussion-subscribe@googlegroups.com * - * @link https://www.smarty.net/ * @author Monte Ohrt * @author Uwe Tews * @author Rodney Rehm @@ -731,7 +730,6 @@ public function setConfigDir($config_dir) { * * @return $this * @throws \Smarty\Exception - * @link https://www.smarty.net/docs/en/api.register.plugin.tpl * * @api Smarty::registerPlugin() */ @@ -758,7 +756,6 @@ public function registerPlugin($type, $name, $callback, $cacheable = true) { * @param string $name name of template tag * * @return array|null - * @link https://www.smarty.net/docs/en/api.unregister.plugin.tpl * * @api Smarty::unregisterPlugin() */ @@ -776,7 +773,6 @@ public function getRegisteredPlugin($type, $name): ?array { * @param string $name name of template tag * * @return $this - * @link https://www.smarty.net/docs/en/api.unregister.plugin.tpl * * @api Smarty::unregisterPlugin() */ @@ -850,7 +846,6 @@ function ($extension) { * * @return $this * @throws Exception if $callback is not callable - * @link https://www.smarty.net/docs/en/api.register.default.plugin.handler.tpl * * @api Smarty::registerDefaultPluginHandler() * @@ -1254,7 +1249,6 @@ public function isMutingUndefinedOrNullWarnings(): bool { * * @return int number of cache files deleted * @throws \Smarty\Exception - * @link https://www.smarty.net/docs/en/api.clear.cache.tpl * * @api Smarty::clearCache() */ @@ -1274,7 +1268,6 @@ public function clearCache( * @param string $type resource type * * @return int number of cache files deleted - * @link https://www.smarty.net/docs/en/api.clear.all.cache.tpl * * @api Smarty::clearAllCache() */ @@ -1291,7 +1284,6 @@ public function clearAllCache($exp_time = null) { * * @return int number of template files deleted * @throws \Smarty\Exception - * @link https://www.smarty.net/docs/en/api.clear.compiled.template.tpl * * @api Smarty::clearCompiledTemplate() */ @@ -1805,7 +1797,6 @@ public function getDefaultPluginHandlerFunc(): ?callable { * @return bool * @throws \Smarty\Exception * @api Smarty::loadFilter() - * @link https://www.smarty.net/docs/en/api.load.filter.tpl * * @deprecated since 5.0 */ @@ -1857,7 +1848,6 @@ public function loadFilter($type, $name) { * @throws \Smarty\Exception * @api Smarty::unloadFilter() * - * @link https://www.smarty.net/docs/en/api.unload.filter.tpl * * @deprecated since 5.0 */ @@ -1901,7 +1891,6 @@ public function getCachingType(): string { * @param Base $resource_handler * * @return Smarty - * @link https://www.smarty.net/docs/en/api.register.cacheresource.tpl * * @api Smarty::registerCacheResource() * @@ -1924,7 +1913,6 @@ public function registerCacheResource($name, \Smarty\Cacheresource\Base $resourc * * @return Smarty * @api Smarty::unregisterCacheResource() - * @link https://www.smarty.net/docs/en/api.unregister.cacheresource.tpl * * @deprecated since 5.0 * @@ -1958,7 +1946,6 @@ private function activateBCCacheResource() { * * @return TemplateBase * @throws \Smarty\Exception - * @link https://www.smarty.net/docs/en/api.register.filter.tpl * * @api Smarty::registerFilter() */ @@ -2020,7 +2007,6 @@ private function _getFilterName($callable) { * @throws \Smarty\Exception * @api Smarty::unregisterFilter() * - * @link https://www.smarty.net/docs/en/api.unregister.filter.tpl * */ public function unregisterFilter($type, $name) { @@ -2203,7 +2189,6 @@ public function doCreateTemplate( * @return bool cache status * @throws \Exception * @throws \Smarty\Exception - * @link https://www.smarty.net/docs/en/api.is.cached.tpl * * @api Smarty::isCached() */ diff --git a/src/Template.php b/src/Template.php index 8bb5370f1..fcb0f58d2 100644 --- a/src/Template.php +++ b/src/Template.php @@ -604,7 +604,6 @@ public function display() { * @return bool cache status * @throws \Exception * @throws \Smarty\Exception - * @link https://www.smarty.net/docs/en/api.is.cached.tpl * * @api Smarty::isCached() */ diff --git a/src/TemplateBase.php b/src/TemplateBase.php index 4dab470f9..0b7f212c1 100644 --- a/src/TemplateBase.php +++ b/src/TemplateBase.php @@ -75,7 +75,6 @@ abstract class TemplateBase extends Data { * * @return \Smarty|\Smarty\Template * @throws \Smarty\Exception - * @link https://www.smarty.net/docs/en/api.register.object.tpl * * @api Smarty::registerObject() */ @@ -116,7 +115,6 @@ public function registerObject( * * @return TemplateBase * @api Smarty::unregisterObject() - * @link https://www.smarty.net/docs/en/api.unregister.object.tpl * */ public function unregisterObject($object_name) { @@ -179,7 +177,6 @@ public function setCacheId($cache_id) { * @return Data data object * @throws Exception * @api Smarty::createData() - * @link https://www.smarty.net/docs/en/api.create.data.tpl * */ public function createData(Data $parent = null, $name = null) { @@ -222,7 +219,6 @@ public function getDebug(): Debug { * * @return object * @throws \Smarty\Exception if no such object is found - * @link https://www.smarty.net/docs/en/api.get.registered.object.tpl * * @api Smarty::getRegisteredObject() */ @@ -319,7 +315,6 @@ private function _setLiterals(Smarty $smarty, $literals) { * @return TemplateBase * @throws \Smarty\Exception * @api Smarty::registerClass() - * @link https://www.smarty.net/docs/en/api.register.class.tpl * */ public function registerClass($class_name, $class_impl) { @@ -380,7 +375,6 @@ public function registerDefaultTemplateHandler($callback) { * @param \Smarty\Resource\BasePlugin $resource_handler instance of Smarty\Resource\BasePlugin * * @return \Smarty\Smarty|\Smarty\Template - * @link https://www.smarty.net/docs/en/api.register.resource.tpl * * @api Smarty::registerResource() */ @@ -397,7 +391,6 @@ public function registerResource($name, \Smarty\Resource\BasePlugin $resource_ha * * @return TemplateBase * @api Smarty::unregisterResource() - * @link https://www.smarty.net/docs/en/api.unregister.resource.tpl * */ public function unregisterResource($type) { diff --git a/tests/UnitTests/SecurityTests/SecurityTest.php b/tests/UnitTests/SecurityTests/SecurityTest.php index e2e66c965..9996f2252 100644 --- a/tests/UnitTests/SecurityTests/SecurityTest.php +++ b/tests/UnitTests/SecurityTests/SecurityTest.php @@ -10,411 +10,411 @@ /** * class for security test - * - * - * - * */ class SecurityTest extends PHPUnit_Smarty { - public function setUp(): void - { - $this->setUpSmarty(__DIR__); - - $this->smarty->setForceCompile(true); - $this->smarty->enableSecurity(); - } - public function testInit() - { - $this->cleanDirs(); - } - -/** -* test that security is loaded - */ - public function testSecurityLoaded() - { - $this->assertTrue(is_object($this->smarty->security_policy)); - } - -/** - * test trusted PHP function - */ - public function testTrustedFunction() - { - $this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{count($foo)}')); - } - -/** - * test trusted modifier - * @deprecated - */ - public function testTrustedModifier() - { - $this->assertEquals("5", @$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}')); - } - -/** - * test not trusted modifier - * - * - * @deprecated - */ - public function testNotTrustedModifier() - { - $this->smarty->security_policy->disabled_modifiers[] = 'escape'; - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('modifier \'escape\' disabled by security setting'); - @$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|escape}'); - } - -/** - * test allowed tags - */ - public function testAllowedTags1() - { - $this->smarty->security_policy->allowed_tags = array('counter'); - $this->assertEquals("1", $this->smarty->fetch('string:{counter start=1}')); - } - -/** - * test not allowed tag - * - * - */ - public function testNotAllowedTags2() - { - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('tag \'cycle\' not allowed by security setting'); - $this->smarty->security_policy->allowed_tags = array('counter'); - $this->smarty->fetch('string:{counter}{cycle values="1,2"}'); - } - -/** - * test disabled tag - * - * - */ - public function testDisabledTags() - { - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('tag \'cycle\' disabled by security setting'); - $this->smarty->security_policy->disabled_tags = array('cycle'); - $this->smarty->fetch('string:{counter}{cycle values="1,2"}'); - } - -/** - * test allowed modifier - */ - public function testAllowedModifier1() - { - error_reporting(E_ALL & E_STRICT); - $this->smarty->security_policy->allowed_modifiers = array('capitalize'); - $this->assertEquals("Hello World", $this->smarty->fetch('string:{"hello world"|capitalize}')); - error_reporting(E_ALL | E_STRICT); - } - - public function testAllowedModifier2() - { - $this->smarty->security_policy->allowed_modifiers = array('upper'); - $this->assertEquals("HELLO WORLD", $this->smarty->fetch('string:{"hello world"|upper}')); - } - -/** - * test not allowed modifier - * - * - */ - public function testNotAllowedModifier() - { - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('modifier \'lower\' not allowed by security setting'); - $this->smarty->security_policy->allowed_modifiers = array('upper'); - $this->smarty->fetch('string:{"hello"|upper}{"world"|lower}'); - } - -/** - * test disabled modifier - * - * - */ - public function testDisabledModifier() - { - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('modifier \'lower\' disabled by security setting'); - $this->smarty->security_policy->disabled_modifiers = array('lower'); - $this->smarty->fetch('string:{"hello"|upper}{"world"|lower}'); - } - - -/** - * test Smarty no longer handles embedded PHP - */ - public function testSmartyPhpAllow() - { - $this->assertEquals('', $this->smarty->fetch('string:')); - } - - public function testSmartyPhpAllow2() - { - $this->assertEquals('', $this->smarty->fetch('string:')); - } - - public function testSmartyPhpAllow3() - { - $this->assertEquals('<% echo "hello world"; %>', $this->smarty->fetch('string:<% echo "hello world"; %>')); - } - -/** - * test standard directory - */ - public function testStandardDirectory() - { - $content = $this->smarty->fetch('string:{include file="helloworld.tpl"}'); - $this->assertEquals("hello world", $content); - } - -/** - * test trusted directory - */ - public function testTrustedDirectory() - { - $this->smarty->security_policy->secure_dir = array('.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR); - $this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}')); - } - -/** - * test not trusted directory - * - * - * - */ - public function testNotTrustedDirectory() - { - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('not trusted file path'); - $this->smarty->security_policy->secure_dir = array(str_replace('\\', '/', __DIR__ . '/templates_3/')); - $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}'); - } - -/** - * test disabled security for not trusted dir - */ - public function testDisabledTrustedDirectory() - { - $this->smarty->disableSecurity(); - $this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}')); - } - -/** - * test trusted static class - */ - public function testTrustedStaticClass() - { - $this->smarty->security_policy->static_classes = array('mysecuritystaticclass'); - $tpl = $this->smarty->createTemplate('string:{mysecuritystaticclass::square(5)}'); - $this->assertEquals('25', $this->smarty->fetch($tpl)); - } - - /** - * test not trusted PHP function - * - * - */ - public function testNotTrustedStaticClass() - { - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('access to static class \'mysecuritystaticclass\' not allowed by security setting'); - $this->smarty->security_policy->static_classes = array('null'); - $this->smarty->fetch('string:{mysecuritystaticclass::square(5)}'); - } - - /** - * test not trusted PHP function - */ - public function testNotTrustedStaticClassEval() - { - $this->expectException(\Smarty\Exception::class); - $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(\Smarty\Exception::class); - $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() - { - $this->smarty->security_policy->secure_dir = array( - '.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR, - ); - $this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}')); - - $this->smarty->security_policy->secure_dir = array( - '.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR, - '.' . DIRECTORY_SEPARATOR . 'templates_3' . DIRECTORY_SEPARATOR, - ); - $this->assertEquals("templates_3", $this->smarty->fetch('string:{include file="templates_3/dirname.tpl"}')); - } -/** - * test template file exits - * - * - * - */ - public function testTemplateTrustedStream() - { - stream_wrapper_register("global", ResourceStreamSecurity::class) - or die("Failed to register protocol"); - $fp = fopen("global://mytest", "r+"); - fwrite($fp, 'hello world {$foo}'); - fclose($fp); - $this->smarty->security_policy->streams= array('global'); - $tpl = $this->smarty->createTemplate('global:mytest'); - $this->assertTrue($tpl->getSource()->exists); - stream_wrapper_unregister("global"); - } -/** - * - * - * test template file exits - */ - public function testTemplateNotTrustedStream() - { - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('stream \'global\' not allowed by security setting'); - stream_wrapper_register("global", ResourceStreamSecurity::class) - or die("Failed to register protocol"); - $fp = fopen("global://mytest", "r+"); - fwrite($fp, 'hello world {$foo}'); - fclose($fp); - $this->smarty->security_policy->streams= array('notrusted'); - $tpl = $this->smarty->createTemplate('global:mytest'); - $this->assertTrue($tpl->getSource()->exists); - stream_wrapper_unregister("global"); - } -/** - * - * @group slow -*/ - public function testTrustedUri() - { - $this->smarty->security_policy->trusted_uri = array( - '#https://www.smarty.net$#i' - ); - $this->assertStringContainsString('Preface | Smarty', $this->smarty->fetch('string:{fetch file="https://www.smarty.net/docs/en/preface.tpl"}')); - } - -/** - * - * -*/ - public function testNotTrustedUri() - { - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('URI \'https://www.smarty.net/docs/en/preface.tpl\' not allowed by security setting'); - $this->smarty->security_policy->trusted_uri = array(); - $this->assertStringContainsString('Preface | Smarty', $this->smarty->fetch('string:{fetch file="https://www.smarty.net/docs/en/preface.tpl"}')); - } - - /** - * In security mode, accessing $smarty.template_object should be illegal. - */ - public function testSmartyTemplateObject() { - $this->expectException(CompilerException::class); - $this->smarty->display('string:{$smarty.template_object}'); - } + public function setUp(): void + { + $this->setUpSmarty(__DIR__); + + $this->smarty->setForceCompile(true); + $this->smarty->enableSecurity(); + } + public function testInit() + { + $this->cleanDirs(); + } + + /** + * test that security is loaded + */ + public function testSecurityLoaded() + { + $this->assertTrue(is_object($this->smarty->security_policy)); + } + + /** + * test trusted PHP function + */ + public function testTrustedFunction() + { + $this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{count($foo)}')); + } + + /** + * test trusted modifier + * @deprecated + */ + public function testTrustedModifier() + { + $this->assertEquals("5", @$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}')); + } + + /** + * test not trusted modifier + * + * + * @deprecated + */ + public function testNotTrustedModifier() + { + $this->smarty->security_policy->disabled_modifiers[] = 'escape'; + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('modifier \'escape\' disabled by security setting'); + @$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|escape}'); + } + + /** + * test allowed tags + */ + public function testAllowedTags1() + { + $this->smarty->security_policy->allowed_tags = array('counter'); + $this->assertEquals("1", $this->smarty->fetch('string:{counter start=1}')); + } + + /** + * test not allowed tag + * + * + */ + public function testNotAllowedTags2() + { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('tag \'cycle\' not allowed by security setting'); + $this->smarty->security_policy->allowed_tags = array('counter'); + $this->smarty->fetch('string:{counter}{cycle values="1,2"}'); + } + + /** + * test disabled tag + * + * + */ + public function testDisabledTags() + { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('tag \'cycle\' disabled by security setting'); + $this->smarty->security_policy->disabled_tags = array('cycle'); + $this->smarty->fetch('string:{counter}{cycle values="1,2"}'); + } + + /** + * test allowed modifier + */ + public function testAllowedModifier1() + { + error_reporting(E_ALL & E_STRICT); + $this->smarty->security_policy->allowed_modifiers = array('capitalize'); + $this->assertEquals("Hello World", $this->smarty->fetch('string:{"hello world"|capitalize}')); + error_reporting(E_ALL | E_STRICT); + } + + public function testAllowedModifier2() + { + $this->smarty->security_policy->allowed_modifiers = array('upper'); + $this->assertEquals("HELLO WORLD", $this->smarty->fetch('string:{"hello world"|upper}')); + } + + /** + * test not allowed modifier + * + * + */ + public function testNotAllowedModifier() + { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('modifier \'lower\' not allowed by security setting'); + $this->smarty->security_policy->allowed_modifiers = array('upper'); + $this->smarty->fetch('string:{"hello"|upper}{"world"|lower}'); + } + + /** + * test disabled modifier + * + * + */ + public function testDisabledModifier() + { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('modifier \'lower\' disabled by security setting'); + $this->smarty->security_policy->disabled_modifiers = array('lower'); + $this->smarty->fetch('string:{"hello"|upper}{"world"|lower}'); + } + + + /** + * test Smarty no longer handles embedded PHP + */ + public function testSmartyPhpAllow() + { + $this->assertEquals('', $this->smarty->fetch('string:')); + } + + public function testSmartyPhpAllow2() + { + $this->assertEquals('', $this->smarty->fetch('string:')); + } + + public function testSmartyPhpAllow3() + { + $this->assertEquals('<% echo "hello world"; %>', $this->smarty->fetch('string:<% echo "hello world"; %>')); + } + + /** + * test standard directory + */ + public function testStandardDirectory() + { + $content = $this->smarty->fetch('string:{include file="helloworld.tpl"}'); + $this->assertEquals("hello world", $content); + } + + /** + * test trusted directory + */ + public function testTrustedDirectory() + { + $this->smarty->security_policy->secure_dir = array('.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR); + $this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}')); + } + + /** + * test not trusted directory + * + * + * + */ + public function testNotTrustedDirectory() + { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('not trusted file path'); + $this->smarty->security_policy->secure_dir = array(str_replace('\\', '/', __DIR__ . '/templates_3/')); + $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}'); + } + + /** + * test disabled security for not trusted dir + */ + public function testDisabledTrustedDirectory() + { + $this->smarty->disableSecurity(); + $this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}')); + } + + /** + * test trusted static class + */ + public function testTrustedStaticClass() + { + $this->smarty->security_policy->static_classes = array('mysecuritystaticclass'); + $tpl = $this->smarty->createTemplate('string:{mysecuritystaticclass::square(5)}'); + $this->assertEquals('25', $this->smarty->fetch($tpl)); + } + + /** + * test not trusted PHP function + * + * + */ + public function testNotTrustedStaticClass() + { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('access to static class \'mysecuritystaticclass\' not allowed by security setting'); + $this->smarty->security_policy->static_classes = array('null'); + $this->smarty->fetch('string:{mysecuritystaticclass::square(5)}'); + } + + /** + * test not trusted PHP function + */ + public function testNotTrustedStaticClassEval() + { + $this->expectException(\Smarty\Exception::class); + $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(\Smarty\Exception::class); + $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() + { + $this->smarty->security_policy->secure_dir = array( + '.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR, + ); + $this->assertEquals("hello world", $this->smarty->fetch('string:{include file="templates_2/hello.tpl"}')); + + $this->smarty->security_policy->secure_dir = array( + '.' . DIRECTORY_SEPARATOR . 'templates_2' . DIRECTORY_SEPARATOR, + '.' . DIRECTORY_SEPARATOR . 'templates_3' . DIRECTORY_SEPARATOR, + ); + $this->assertEquals("templates_3", $this->smarty->fetch('string:{include file="templates_3/dirname.tpl"}')); + } + /** + * test template file exits + * + * + * + */ + public function testTemplateTrustedStream() + { + stream_wrapper_register("global", ResourceStreamSecurity::class) + or die("Failed to register protocol"); + $fp = fopen("global://mytest", "r+"); + fwrite($fp, 'hello world {$foo}'); + fclose($fp); + $this->smarty->security_policy->streams= array('global'); + $tpl = $this->smarty->createTemplate('global:mytest'); + $this->assertTrue($tpl->getSource()->exists); + stream_wrapper_unregister("global"); + } + /** + * + * + * test template file exits + */ + public function testTemplateNotTrustedStream() + { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('stream \'global\' not allowed by security setting'); + stream_wrapper_register("global", ResourceStreamSecurity::class) + or die("Failed to register protocol"); + $fp = fopen("global://mytest", "r+"); + fwrite($fp, 'hello world {$foo}'); + fclose($fp); + $this->smarty->security_policy->streams= array('notrusted'); + $tpl = $this->smarty->createTemplate('global:mytest'); + $this->assertTrue($tpl->getSource()->exists); + stream_wrapper_unregister("global"); + } + + public function testTrustedUri() + { + $this->smarty->security_policy->trusted_uri = array( + '#https://s4otw4nhg.erteorteortert.nusuchtld$#i' + ); + + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('{fetch} cannot read resource \'https://s4otw4nhg.erteorteortert.nusuchtld/docs/en/preface.tpl\''); + + $this->smarty->fetch('string:{fetch file="https://s4otw4nhg.erteorteortert.nusuchtld/docs/en/preface.tpl"}'); + } + + /** + * + * + */ + public function testNotTrustedUri() + { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('URI \'https://example.net\' not allowed by security setting'); + $this->smarty->security_policy->trusted_uri = []; + $this->assertStringContainsString( + 'Preface | Smarty', + $this->smarty->fetch('string:{fetch file="https://example.net"}') + ); + } + + /** + * In security mode, accessing $smarty.template_object should be illegal. + */ + public function testSmartyTemplateObject() { + $this->expectException(CompilerException::class); + $this->smarty->display('string:{$smarty.template_object}'); + } } class mysecuritystaticclass { - const STATIC_CONSTANT_VALUE = 3; - static $static_var = 5; + const STATIC_CONSTANT_VALUE = 3; + static $static_var = 5; - static function square($i) - { - return $i * $i; - } + static function square($i) + { + return $i * $i; + } } #[AllowDynamicProperties] class ResourceStreamSecurity { - private $position; - private $varname; - - public function stream_open($path, $mode, $options, &$opened_path) - { - $url = parse_url($path); - $this->varname = $url["host"]; - $this->position = 0; - - return true; - } - - public function stream_read($count) - { - $p = &$this->position; - $ret = substr($GLOBALS[$this->varname], $p, $count); - $p += strlen($ret); - - return $ret; - } - - public function stream_write($data) - { - $v = &$GLOBALS[$this->varname]; - $l = strlen($data); - $p = &$this->position; - $v = substr($v ?? '', 0, $p) . $data . substr($v ?? '', $p += $l); - - return $l; - } - - public function stream_tell() - { - return $this->position; - } - - public function stream_eof() - { - if (!isset($GLOBALS[$this->varname])) { - return true; - } - - return $this->position >= strlen($GLOBALS[$this->varname]); - } - - public function stream_seek($offset, $whence) - { - $l = strlen($GLOBALS[$this->varname]); - $p = &$this->position; - switch ($whence) { - case SEEK_SET: - $newPos = $offset; - break; - case SEEK_CUR: - $newPos = $p + $offset; - break; - case SEEK_END: - $newPos = $l + $offset; - break; - default: - return false; - } - $ret = ($newPos >= 0 && $newPos <= $l); - if ($ret) { - $p = $newPos; - } - return $ret; - } + private $position; + private $varname; + + public function stream_open($path, $mode, $options, &$opened_path) + { + $url = parse_url($path); + $this->varname = $url["host"]; + $this->position = 0; + + return true; + } + + public function stream_read($count) + { + $p = &$this->position; + $ret = substr($GLOBALS[$this->varname], $p, $count); + $p += strlen($ret); + + return $ret; + } + + public function stream_write($data) + { + $v = &$GLOBALS[$this->varname]; + $l = strlen($data); + $p = &$this->position; + $v = substr($v ?? '', 0, $p) . $data . substr($v ?? '', $p += $l); + + return $l; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + if (!isset($GLOBALS[$this->varname])) { + return true; + } + + return $this->position >= strlen($GLOBALS[$this->varname]); + } + + public function stream_seek($offset, $whence) + { + $l = strlen($GLOBALS[$this->varname]); + $p = &$this->position; + switch ($whence) { + case SEEK_SET: + $newPos = $offset; + break; + case SEEK_CUR: + $newPos = $p + $offset; + break; + case SEEK_END: + $newPos = $l + $offset; + break; + default: + return false; + } + $ret = ($newPos >= 0 && $newPos <= $l); + if ($ret) { + $p = $newPos; + } + return $ret; + } } diff --git a/tests/UnitTests/TemplateSource/TagTests/PluginFunction/PluginFunctionFetchTest.php b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/PluginFunctionFetchTest.php index d9899e3c4..5c3aa45ee 100644 --- a/tests/UnitTests/TemplateSource/TagTests/PluginFunction/PluginFunctionFetchTest.php +++ b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/PluginFunctionFetchTest.php @@ -1,85 +1,71 @@ setUpSmarty(__DIR__); - } + public function setUp(): void + { + $this->setUpSmarty(__DIR__); + } - public function testInit() - { - $this->cleanDirs(); - } + public function testInit() + { + $this->cleanDirs(); + } + /** + * test {fetch} from local file + */ + public function testFetchFile() + { + $this->assertStringContainsString( + 'ct4hn8nzgm;cgzm;', + $this->smarty->fetch('string:{fetch file="./testfile.txt"}') + ); + } -/** -* test {fetch} from UIR -* -* -* @group slow -*/ - public function testFetchUri() - { - $this->assertStringContainsString('Preface | Smarty', $this->smarty->fetch('string:{fetch file="https://www.smarty.net/docs/en/preface.tpl"}')); - } - -/** -* test {fetch} invalid uri -* -* -* -*/ - public function testFetchInvalidUri() - { - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('{fetch} cannot read resource \'https://foo.smarty.net/foo.dat\''); - $this->smarty->fetch('string:{fetch file="https://foo.smarty.net/foo.dat"}'); - } + /** + * test {fetch} non-existing file + */ + public function testFetchNonExistingFile() + { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('{fetch} cannot read resource \'./no/such/file\''); + $this->smarty->fetch('string:{fetch file="./no/such/file"}'); + } - /** - * test {fetch file=...} access to file from path not aloo/wed by security settings - * - * @run InSeparateProcess - * - */ - public function testFetchSecurity() - { - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('not trusted file path'); - $this->cleanDirs(); - $dir=$this->smarty->getTemplateDir(); - $this->smarty->enableSecurity(); - $this->smarty->fetch('string:{fetch file=\''. $dir[0]. '../../../../../etc/passwd\'}'); - } - /** - * test {fetch file=...} access to file from path not aloo/wed by security settings - * - * @run InSeparateProcess - * - */ - public function testFetchSecurity2() - { - $this->expectException(\Smarty\Exception::class); - $this->expectExceptionMessage('not trusted file path'); - $this->cleanDirs(); - $this->smarty->getTemplateDir(); - $this->smarty->enableSecurity(); - $this->smarty->setTemplateDir('/templates'); - $this->smarty->fetch('string:{fetch file="/templates/../etc/passwd"}'); - } + /** + * test {fetch file=...} access to file from path not aloo/wed by security settings + * + * @run InSeparateProcess + * + */ + public function testFetchSecurity() + { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('not trusted file path'); + $this->cleanDirs(); + $dir=$this->smarty->getTemplateDir(); + $this->smarty->enableSecurity(); + $this->smarty->fetch('string:{fetch file=\''. $dir[0]. '../../../../../etc/passwd\'}'); + } + /** + * test {fetch file=...} access to file from path not aloo/wed by security settings + * + * @run InSeparateProcess + * + */ + public function testFetchSecurity2() + { + $this->expectException(\Smarty\Exception::class); + $this->expectExceptionMessage('not trusted file path'); + $this->cleanDirs(); + $this->smarty->getTemplateDir(); + $this->smarty->enableSecurity(); + $this->smarty->setTemplateDir('/templates'); + $this->smarty->fetch('string:{fetch file="/templates/../etc/passwd"}'); + } } diff --git a/tests/UnitTests/TemplateSource/TagTests/PluginFunction/testfile.txt b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/testfile.txt new file mode 100644 index 000000000..4efd4a719 --- /dev/null +++ b/tests/UnitTests/TemplateSource/TagTests/PluginFunction/testfile.txt @@ -0,0 +1 @@ +ct4hn8nzgm;cgzm; \ No newline at end of file