diff --git a/public/backup/util/dbops/backup_plan_dbops.class.php b/public/backup/util/dbops/backup_plan_dbops.class.php index bb002c44127..ce2bb002f54 100644 --- a/public/backup/util/dbops/backup_plan_dbops.class.php +++ b/public/backup/util/dbops/backup_plan_dbops.class.php @@ -362,9 +362,10 @@ abstract class backup_plan_dbops extends backup_dbops { * @return mustache_engine */ private static function get_mustache_for_filename_generation(): mustache_engine { + $stringhelper = new mustache_string_helper(); return new mustache_engine([ 'helpers' => [ - 'str' => [new mustache_string_helper(), 'str'], + 'str' => fn($text, $helper) => $stringhelper->str($text, $helper), ], ]); } diff --git a/public/lib/classes/component.php b/public/lib/classes/component.php index 2294048fa57..3c4e38ce8f4 100644 --- a/public/lib/classes/component.php +++ b/public/lib/classes/component.php @@ -110,7 +110,6 @@ class component { protected static $filestomap = ['lib.php', 'settings.php']; /** @var array associative array of PSR-0 namespaces and corresponding paths. */ protected static $psr0namespaces = [ - 'Mustache' => 'public/lib/mustache/src/Mustache', ]; /** @var array> associative array of PRS-4 namespaces and corresponding paths. */ protected static $psr4namespaces = [ @@ -141,6 +140,7 @@ class component { \MoodleHQ::class => [ 'public/lib/rtlcss/src/MoodleHQ', ], + \Mustache::class => 'public/lib/mustache/src', \OpenSpout::class => 'public/lib/openspout/src', \Packback\Lti1p3::class => 'public/lib/lti1p3/src', \PHPMailer\PHPMailer::class => 'public/lib/phpmailer/src', diff --git a/public/lib/classes/output/mustache_clean_string_helper.php b/public/lib/classes/output/mustache_clean_string_helper.php index 3cda336720b..acb2ab173d5 100644 --- a/public/lib/classes/output/mustache_clean_string_helper.php +++ b/public/lib/classes/output/mustache_clean_string_helper.php @@ -16,7 +16,7 @@ namespace core\output; -use Mustache_LambdaHelper; +use Mustache\LambdaHelper; /** * This class will load language strings in a template. @@ -50,10 +50,10 @@ class mustache_clean_string_helper { * The last is a $a argument for get string. For complex data here, use JSON. * * @param string $text The text to parse for arguments. - * @param Mustache_LambdaHelper $helper Used to render nested mustache variables. + * @param LambdaHelper $helper Used to render nested mustache variables. * @return string */ - public function cleanstr($text, Mustache_LambdaHelper $helper) { + public function cleanstr($text, LambdaHelper $helper) { return s($this->stringhelper->str($text, $helper)); } } diff --git a/public/lib/classes/output/mustache_engine.php b/public/lib/classes/output/mustache_engine.php index 5bea960264d..39acf03959d 100644 --- a/public/lib/classes/output/mustache_engine.php +++ b/public/lib/classes/output/mustache_engine.php @@ -31,7 +31,7 @@ namespace core\output; * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @package core */ -class mustache_engine extends \Mustache_Engine { +class mustache_engine extends \Mustache\Engine { /** * @var mustache_helper_collection */ @@ -45,7 +45,7 @@ class mustache_engine extends \Mustache_Engine { /** * Mustache engine constructor. * - * This provides an additional option to the parent \Mustache_Engine implementation: + * This provides an additional option to the parent \Mustache\Engine implementation: * $options = [ * // A list of helpers (by name) to prevent from executing within the rendering * // of other helpers. @@ -70,9 +70,9 @@ class mustache_engine extends \Mustache_Engine { /** * Get the current set of Mustache helpers. * - * @see \Mustache_Engine::setHelpers + * @see \Mustache\Engine::setHelpers * - * @return \Mustache_HelperCollection + * @return \Mustache\HelperCollection */ public function gethelpers() { if (!isset($this->helpers)) { diff --git a/public/lib/classes/output/mustache_filesystem_loader.php b/public/lib/classes/output/mustache_filesystem_loader.php index bebebc1dcfe..d559cd883c8 100644 --- a/public/lib/classes/output/mustache_filesystem_loader.php +++ b/public/lib/classes/output/mustache_filesystem_loader.php @@ -24,7 +24,7 @@ namespace core\output; * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since 2.9 */ -class mustache_filesystem_loader extends \Mustache_Loader_FilesystemLoader { +class mustache_filesystem_loader extends \Mustache\Loader\FilesystemLoader { /** * Provide a default no-args constructor (we don't really need anything). */ diff --git a/public/lib/classes/output/mustache_helper_collection.php b/public/lib/classes/output/mustache_helper_collection.php index 092ecbf29da..7b8be3eed9b 100644 --- a/public/lib/classes/output/mustache_helper_collection.php +++ b/public/lib/classes/output/mustache_helper_collection.php @@ -16,6 +16,10 @@ namespace core\output; +use Mustache\HelperCollection; +use Mustache\LambdaHelper; +use Mustache\Tokenizer; + /** * Custom Moodle helper collection for mustache. * @@ -23,7 +27,7 @@ namespace core\output; * @copyright 2019 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class mustache_helper_collection extends \Mustache_HelperCollection { +class mustache_helper_collection extends HelperCollection { /** * @var string[] Names of helpers that aren't allowed to be called within other helpers. */ @@ -34,7 +38,7 @@ class mustache_helper_collection extends \Mustache_HelperCollection { * * Optionally accepts an array (or Traversable) of `$name => $helper` pairs. * - * @throws \Mustache_Exception_InvalidArgumentException if the $helpers argument isn't an array or Traversable + * @throws \Mustache\Exception\InvalidArgumentException if the $helpers argument isn't an array or Traversable * * @param array|\Traversable $helpers (default: null) * @param string[] $disallowednestedhelpers Names of helpers that aren't allowed to be called within other helpers. @@ -57,7 +61,7 @@ class mustache_helper_collection extends \Mustache_HelperCollection { * helper function. This prevents the disallowed helper functions from being * called by nested render functions from within other helpers. * - * @see \Mustache_HelperCollection::add() + * @see \Mustache\HelperCollection::add() * @param string $name * @param mixed $helper */ @@ -66,7 +70,7 @@ class mustache_helper_collection extends \Mustache_HelperCollection { $disallowedlist = $this->disallowednestedhelpers; if (is_callable($helper) && !empty($disallowedlist)) { - $helper = function ($source, \Mustache_LambdaHelper $lambdahelper) use ($helper, $disallowedlist) { + $helper = function ($source, LambdaHelper $lambdahelper) use ($helper, $disallowedlist) { // Temporarily override the disallowed helpers to return nothing // so that they can't be executed from within other helpers. @@ -77,12 +81,14 @@ class mustache_helper_collection extends \Mustache_HelperCollection { // that this helper has finished executing so that the rest of // the rendering process continues to work correctly. $this->restore_helpers($disabledhelpers); - // Lastly parse the returned string to strip out any unwanted helper + // Parse the returned string to strip out any unwanted helper // tags that were added through variable substitution (or other means). // This is done because a secondary render is called on the result // of a helper function if it still includes mustache tags. See - // the section function of Mustache_Compiler for details. - return $this->strip_disallowed_helpers($disallowedlist, $result); + // the section function of \Mustache\Compiler for details. + $stripped = $this->strip_disallowed_helpers($disallowedlist, $result); + // Prevent re-rendering by wrapping in RenderedString. + return $lambdahelper->preventRender($stripped); }; } @@ -142,8 +148,8 @@ class mustache_helper_collection extends \Mustache_HelperCollection { * @return string Parsed string */ public function strip_disallowed_helpers($disallowedlist, $string) { - $starttoken = \Mustache_Tokenizer::T_SECTION; - $endtoken = \Mustache_Tokenizer::T_END_SECTION; + $starttoken = Tokenizer::T_SECTION; + $endtoken = Tokenizer::T_END_SECTION; if ($endtoken == '/') { $endtoken = '\/'; } diff --git a/public/lib/classes/output/mustache_javascript_helper.php b/public/lib/classes/output/mustache_javascript_helper.php index eb3ce6df69f..6ce33abfaad 100644 --- a/public/lib/classes/output/mustache_javascript_helper.php +++ b/public/lib/classes/output/mustache_javascript_helper.php @@ -16,6 +16,8 @@ namespace core\output; +use Mustache\LambdaHelper; + /** * Store a list of JS calls to insert at the end of the page. * @@ -44,10 +46,10 @@ class mustache_javascript_helper { * This function will always return an empty string because the JS is added to the page via the requirements manager. * * @param string $text The script content of the section. - * @param \Mustache_LambdaHelper $helper Used to render the content of this block. + * @param LambdaHelper $helper Used to render the content of this block. * @return string The text of the block */ - public function help($text, \Mustache_LambdaHelper $helper) { + public function help($text, LambdaHelper $helper) { $this->page->requires->js_amd_inline($helper->render($text)); return ''; } diff --git a/public/lib/classes/output/mustache_pix_helper.php b/public/lib/classes/output/mustache_pix_helper.php index 1942f97e8f9..0a73c73882b 100644 --- a/public/lib/classes/output/mustache_pix_helper.php +++ b/public/lib/classes/output/mustache_pix_helper.php @@ -16,7 +16,7 @@ namespace core\output; -use Mustache_LambdaHelper; +use Mustache\LambdaHelper; /** * This class will call pix_icon with the section content. @@ -45,21 +45,21 @@ class mustache_pix_helper { * The args are comma separated and only the first is required. * * @param string $text The text to parse for arguments. - * @param Mustache_LambdaHelper $helper Used to render nested mustache variables. + * @param LambdaHelper $helper Used to render nested mustache variables. * @return string */ - public function pix($text, Mustache_LambdaHelper $helper) { + public function pix($text, LambdaHelper $helper) { // Split the text into an array of variables. $key = strtok($text, ","); - $key = trim($helper->render($key)); + $key = trim((string) $helper->render($key)); $component = strtok(","); - $component = trim($helper->render($component)); + $component = trim((string) $helper->render($component)); if (!$component) { $component = ''; } $text = strtok(""); // Allow mustache tags in the last argument. - $text = trim($helper->render($text)); + $text = trim((string) $helper->render($text)); // The $text has come from a template, so HTML special // chars have been escaped. However, render_pix_icon // assumes the alt arrives with no escaping. So we need diff --git a/public/lib/classes/output/mustache_quote_helper.php b/public/lib/classes/output/mustache_quote_helper.php index 3ecca9e1016..44f9f127020 100644 --- a/public/lib/classes/output/mustache_quote_helper.php +++ b/public/lib/classes/output/mustache_quote_helper.php @@ -25,6 +25,8 @@ namespace core\output; +use Mustache\LambdaHelper; + /** * Wrap content in quotes, and escape all special JSON characters used. * @@ -38,15 +40,15 @@ class mustache_quote_helper { * Note: This helper is only compatible with the standard {{ }} delimeters. * * @param string $text The text to parse for arguments. - * @param \Mustache_LambdaHelper $helper Used to render nested mustache variables. + * @param LambdaHelper $helper Used to render nested mustache variables. * @return string */ - public function quote($text, \Mustache_LambdaHelper $helper) { + public function quote($text, LambdaHelper $helper) { $content = trim($text); $content = $helper->render($content); // Escape the {{ and JSON encode. - $content = json_encode($content); + $content = json_encode((string) $content); $content = preg_replace('([{}]{2,3})', '{{=<% %>=}}${0}<%={{ }}=%>', $content); return $content; } diff --git a/public/lib/classes/output/mustache_shorten_text_helper.php b/public/lib/classes/output/mustache_shorten_text_helper.php index b7151fa985f..da14b6d0882 100644 --- a/public/lib/classes/output/mustache_shorten_text_helper.php +++ b/public/lib/classes/output/mustache_shorten_text_helper.php @@ -16,7 +16,7 @@ namespace core\output; -use Mustache_LambdaHelper; +use Mustache\LambdaHelper; /** * This class will call shorten_text with the section content. @@ -34,18 +34,18 @@ class mustache_shorten_text_helper { * Both args are required. The length must come first. * * @param string $args The text to parse for arguments. - * @param Mustache_LambdaHelper $helper Used to render nested mustache variables. + * @param LambdaHelper $helper Used to render nested mustache variables. * @return string */ - public function shorten($args, Mustache_LambdaHelper $helper) { + public function shorten($args, LambdaHelper $helper) { // Split the text into an array of variables. [$length, $text] = explode(',', $args, 2); $length = trim($length); $text = trim($text); // Allow mustache tags in the length and text. - $text = $helper->render($text); - $length = $helper->render($length); + $text = (string) $helper->render($text); + $length = (int) (string) $helper->render($length); return shorten_text($text, $length); } diff --git a/public/lib/classes/output/mustache_string_helper.php b/public/lib/classes/output/mustache_string_helper.php index 453c49a970b..8b35e25f7cd 100644 --- a/public/lib/classes/output/mustache_string_helper.php +++ b/public/lib/classes/output/mustache_string_helper.php @@ -16,7 +16,7 @@ namespace core\output; -use Mustache_LambdaHelper; +use Mustache\LambdaHelper; use stdClass; /** @@ -41,10 +41,10 @@ class mustache_string_helper { * The last is a $a argument for get string. For complex data here, use JSON. * * @param string $text The text to parse for arguments. - * @param Mustache_LambdaHelper $helper Used to render nested mustache variables. + * @param LambdaHelper $helper Used to render nested mustache variables. * @return string */ - public function str($text, Mustache_LambdaHelper $helper) { + public function str(string $text, LambdaHelper $helper) { // Split the text into an array of variables. $key = strtok($text, ","); $key = trim($key); @@ -60,9 +60,9 @@ class mustache_string_helper { $next = trim($next); if ((strpos($next, '{') === 0) && (strpos($next, '{{') !== 0)) { $rawjson = $helper->render($next); - $a = json_decode($rawjson); + $a = json_decode((string) $rawjson); } else { - $a = $helper->render($next); + $a = (string) $helper->render($next); } return get_string($key, $component, $a); } diff --git a/public/lib/classes/output/mustache_template_source_loader.php b/public/lib/classes/output/mustache_template_source_loader.php index 039a9ed5851..09e1cd41030 100644 --- a/public/lib/classes/output/mustache_template_source_loader.php +++ b/public/lib/classes/output/mustache_template_source_loader.php @@ -16,7 +16,7 @@ namespace core\output; -use Mustache_Tokenizer; +use Mustache\Tokenizer; /** * Load template source strings. @@ -279,7 +279,7 @@ class mustache_template_source_loader { * @return array */ protected function scan_template_source_for_dependencies(string $source): array { - $tokenizer = new Mustache_Tokenizer(); + $tokenizer = new Tokenizer(); $tokens = $tokenizer->scan($source); $templates = []; $strings = []; @@ -304,15 +304,15 @@ class mustache_template_source_loader { if ($name) { switch ($type) { - case Mustache_Tokenizer::T_PARTIAL: + case Tokenizer::T_PARTIAL: [$component, $id] = explode('/', $name, 2); $templates = $addtodependencies($templates, $component, $id); break; - case Mustache_Tokenizer::T_PARENT: + case Tokenizer::T_PARENT: [$component, $id] = explode('/', $name, 2); $templates = $addtodependencies($templates, $component, $id); break; - case Mustache_Tokenizer::T_SECTION: + case Tokenizer::T_SECTION: if ($name == 'str') { [$id, $component] = $this->get_string_identifiers($tokens, $index); @@ -345,7 +345,7 @@ class mustache_template_source_loader { $parts = []; // Get the contents of the string tag. - while ($tokens[$current]['type'] !== Mustache_Tokenizer::T_END_SECTION) { + while ($tokens[$current]['type'] !== Tokenizer::T_END_SECTION) { if (!isset($tokens[$current]['value']) || empty(trim($tokens[$current]['value']))) { // An empty line, so we should ignore it. $current++; diff --git a/public/lib/classes/output/mustache_user_date_helper.php b/public/lib/classes/output/mustache_user_date_helper.php index a087624ec67..5a9593ef75e 100644 --- a/public/lib/classes/output/mustache_user_date_helper.php +++ b/public/lib/classes/output/mustache_user_date_helper.php @@ -16,7 +16,7 @@ namespace core\output; -use Mustache_LambdaHelper; +use Mustache\LambdaHelper; /** * Mustache helper that will convert a timestamp to a date string. @@ -36,10 +36,10 @@ class mustache_user_date_helper { * Both args are required. The timestamp must come first. * * @param string $args The text to parse for arguments. - * @param Mustache_LambdaHelper $helper Used to render nested mustache variables. + * @param LambdaHelper $helper Used to render nested mustache variables. * @return string */ - public function transform($args, Mustache_LambdaHelper $helper) { + public function transform($args, LambdaHelper $helper) { // Split the text into an array of variables. [$timestamp, $format] = explode(',', $args, 2); $timestamp = trim($timestamp); diff --git a/public/lib/classes/output/renderer_base.php b/public/lib/classes/output/renderer_base.php index 308a3253fe8..9c740b61245 100644 --- a/public/lib/classes/output/renderer_base.php +++ b/public/lib/classes/output/renderer_base.php @@ -23,7 +23,7 @@ use core\output\actions\component_action; use moodle_page; use moodle_url; use stdClass; -use Mustache_Exception_UnknownTemplateException; +use Mustache\Exception\UnknownTemplateException; /** * Simple base class for Moodle renderers. @@ -55,7 +55,7 @@ class renderer_base { protected $target; /** - * @var \Mustache_Engine The mustache template compiler + * @var \Mustache\Engine The mustache template compiler */ private $mustache; @@ -68,7 +68,7 @@ class renderer_base { * Return an instance of the mustache class. * * @since 2.9 - * @return \Mustache_Engine + * @return \Mustache\Engine */ protected function get_mustache() { global $CFG; @@ -106,27 +106,24 @@ class renderer_base { $safeconfig = $this->page->requires->get_config_for_javascript($this->page, $this); $helpers = ['config' => $safeconfig, - 'str' => [$stringhelper, 'str'], - 'cleanstr' => [$cleanstringhelper, 'cleanstr'], - 'quote' => [$quotehelper, 'quote'], - 'js' => [$jshelper, 'help'], - 'pix' => [$pixhelper, 'pix'], - 'shortentext' => [$shortentexthelper, 'shorten'], - 'userdate' => [$userdatehelper, 'transform'], - ]; + 'str' => [$stringhelper, 'str'], + 'cleanstr' => [$cleanstringhelper, 'cleanstr'], + 'quote' => [$quotehelper, 'quote'], + 'js' => [$jshelper, 'help'], + 'pix' => [$pixhelper, 'pix'], + 'shortentext' => [$shortentexthelper, 'shorten'], + 'userdate' => [$userdatehelper, 'transform'], + ]; $this->mustache = new mustache_engine([ 'cache' => $cachedir, 'escape' => 's', 'loader' => $loader, 'helpers' => $helpers, - 'pragmas' => [\Mustache_Engine::PRAGMA_BLOCKS], // Don't allow the JavaScript helper to be executed from within another // helper. If it's allowed it can be used by users to inject malicious // JS into the page. 'disallowednestedhelpers' => ['js'], - // Disable lambda rendering - content in helpers is already rendered, no need to render it again. - 'disable_lambda_rendering' => true, ]); } @@ -184,7 +181,7 @@ class renderer_base { try { $template = $mustache->loadTemplate($templatename); $this->templatecache[$templatename] = $template; - } catch (Mustache_Exception_UnknownTemplateException $e) { + } catch (UnknownTemplateException $e) { throw new moodle_exception('Unknown template: ' . $templatename); } } diff --git a/public/lib/emoji-data/generate_emoji_data.php b/public/lib/emoji-data/generate_emoji_data.php index 720e9b1ab22..ce08046387d 100644 --- a/public/lib/emoji-data/generate_emoji_data.php +++ b/public/lib/emoji-data/generate_emoji_data.php @@ -132,7 +132,7 @@ $emojibyshortname = array_reduce($jsondata, function($carry, $data) { return $carry; }, []); -$loader = new \Mustache_Loader_ArrayLoader([ +$loader = new \Mustache\Loader\ArrayLoader([ 'data.js' => file_get_contents('./data.js.mustache') ]); $mustache = new \core\output\mustache_engine(['loader' => $loader]); diff --git a/public/lib/tests/core_renderer_template_exploit_test.php b/public/lib/tests/core_renderer_template_exploit_test.php index a80fba2da77..0509295a8f1 100644 --- a/public/lib/tests/core_renderer_template_exploit_test.php +++ b/public/lib/tests/core_renderer_template_exploit_test.php @@ -414,7 +414,7 @@ final class core_renderer_template_exploit_test extends \advanced_testcase { // Swap the loader out with an array loader so that we can set some // inline templates for testing. - $loader = new \Mustache_Loader_ArrayLoader([]); + $loader = new \Mustache\Loader\ArrayLoader([]); $engine->setLoader($loader); // Add our test helpers. diff --git a/public/lib/tests/output/mustache_clean_string_helper_test.php b/public/lib/tests/output/mustache_clean_string_helper_test.php index 0abc30b9989..1db3e3b5b2f 100644 --- a/public/lib/tests/output/mustache_clean_string_helper_test.php +++ b/public/lib/tests/output/mustache_clean_string_helper_test.php @@ -35,9 +35,9 @@ final class mustache_clean_string_helper_test extends \basic_testcase { * @covers ::cleanstr */ function test_cleanstr(): void { - $engine = new \Mustache_Engine(); - $context = new \Mustache_Context(); - $lambdahelper = new \Mustache_LambdaHelper($engine, $context); + $engine = new \Mustache\Engine(); + $context = new \Mustache\Context(); + $lambdahelper = new \Mustache\LambdaHelper($engine, $context); $cleanstringhelper = new mustache_clean_string_helper(); diff --git a/public/lib/tests/output/mustache_helper_collection_test.php b/public/lib/tests/output/mustache_helper_collection_test.php index 6f49130a1b8..9a8a7f0044b 100644 --- a/public/lib/tests/output/mustache_helper_collection_test.php +++ b/public/lib/tests/output/mustache_helper_collection_test.php @@ -141,9 +141,9 @@ final class mustache_helper_collection_test extends \advanced_testcase { * execution of a helper. */ public function test_disallowed_helpers_disabled_during_execution(): void { - $engine = new \Mustache_Engine(); - $context = new \Mustache_Context(); - $lambdahelper = new \Mustache_LambdaHelper($engine, $context); + $engine = new \Mustache\Engine(); + $context = new \Mustache\Context(); + $lambdahelper = new \Mustache\LambdaHelper($engine, $context); $disallowed = ['bad']; $collection = new mustache_helper_collection(null, $disallowed); $badcalled = false; diff --git a/public/lib/tests/output/mustache_quote_helper_test.php b/public/lib/tests/output/mustache_quote_helper_test.php index 4a3085eb311..c4f436e6523 100644 --- a/public/lib/tests/output/mustache_quote_helper_test.php +++ b/public/lib/tests/output/mustache_quote_helper_test.php @@ -35,12 +35,12 @@ final class mustache_quote_helper_test extends \basic_testcase { * @covers ::quote */ public function test_quote(): void { - $engine = new \Mustache_Engine(); - $context = new \Mustache_Context([ + $engine = new \Mustache\Engine(); + $context = new \Mustache\Context([ 'world' => '{{planet}}', 'planet' => '' ]); - $lambdahelper = new \Mustache_LambdaHelper($engine, $context); + $lambdahelper = new \Mustache\LambdaHelper($engine, $context); $quotehelper = new mustache_quote_helper();