diff --git a/lib/tests/externallib_test.php b/lib/tests/externallib_test.php index 85605c828c6..5da574753f8 100644 --- a/lib/tests/externallib_test.php +++ b/lib/tests/externallib_test.php @@ -183,6 +183,7 @@ class core_externallib_testcase extends advanced_testcase { $correct = 'ENFR hi there%'; $this->assertSame($correct, external_format_string($test, $context->id, false, ['filter' => false])); + $this->assertSame("& < > \" '", format_string("& < > \" '", true, ['escape' => false])); $settings->set_raw($currentraw); $settings->set_filter($currentfilter); diff --git a/lib/tests/weblib_test.php b/lib/tests/weblib_test.php index f2a60e35bc0..3d6caccbbcf 100644 --- a/lib/tests/weblib_test.php +++ b/lib/tests/weblib_test.php @@ -37,6 +37,7 @@ class core_weblib_testcase extends advanced_testcase { $this->assertSame("ANother & &&&&& Category", format_string("ANother & &&&&& Category")); $this->assertSame("ANother & &&&&& Category", format_string("ANother & &&&&& Category", true)); $this->assertSame("Nick's Test Site & Other things", format_string("Nick's Test Site & Other things", true)); + $this->assertSame("& < > \" '", format_string("& < > \" '", true, ['escape' => false])); // String entities. $this->assertSame(""", format_string(""")); diff --git a/lib/weblib.php b/lib/weblib.php index f8d3f0f8a43..94e21fe67f5 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -1380,13 +1380,15 @@ function format_string($string, $striplinks = true, $options = null) { $options['filter'] = true; } + $options['escape'] = !isset($options['escape']) || $options['escape']; + if (!$options['context']) { // We did not find any context? weird. return $string = strip_tags($string); } // Calculate md5. - $md5 = md5($string.'<+>'.$striplinks.'<+>'.$options['context']->id.'<+>'.current_language()); + $md5 = md5($string.'<+>'.$striplinks.'<+>'.$options['context']->id.'<+>'.$options['escape'].'<+>'.current_language()); // Fetch from cache if possible. if (isset($strcache[$md5])) { @@ -1395,7 +1397,7 @@ function format_string($string, $striplinks = true, $options = null) { // First replace all ampersands not followed by html entity code // Regular expression moved to its own method for easier unit testing. - $string = replace_ampersands_not_followed_by_entity($string); + $string = $options['escape'] ? replace_ampersands_not_followed_by_entity($string) : $string; if (!empty($CFG->filterall) && $options['filter']) { $filtermanager = filter_manager::instance(); @@ -1405,8 +1407,11 @@ function format_string($string, $striplinks = true, $options = null) { // If the site requires it, strip ALL tags from this string. if (!empty($CFG->formatstringstriptags)) { - $string = str_replace(array('<', '>'), array('<', '>'), strip_tags($string)); - + if ($options['escape']) { + $string = str_replace(array('<', '>'), array('<', '>'), strip_tags($string)); + } else { + $string = strip_tags($string); + } } else { // Otherwise strip just links if that is required (default). if ($striplinks) {