diff --git a/lib/setuplib.php b/lib/setuplib.php index a0814bee8eb..3723dba5e71 100644 --- a/lib/setuplib.php +++ b/lib/setuplib.php @@ -557,10 +557,16 @@ function get_exception_info($ex) { } } - // when printing an error the continue button should never link offsite - if (stripos($link, $CFG->wwwroot) === false && - stripos($link, $CFG->httpswwwroot) === false) { - $link = $CFG->wwwroot.'/'; + // When printing an error the continue button should never link offsite. + // We cannot use clean_param() here as it is not guaranteed that it has been loaded yet. + $httpswwwroot = str_replace('http:', 'https:', $CFG->wwwroot); + if (stripos($link, $CFG->wwwroot) === 0) { + // Internal HTTP, all good. + } else if (!empty($CFG->loginhttps) && stripos($link, $httpswwwroot) === 0) { + // Internal HTTPS, all good. + } else { + // External link spotted! + $link = $CFG->wwwroot . '/'; } $info = new stdClass(); diff --git a/lib/tests/setuplib_test.php b/lib/tests/setuplib_test.php index 96fffada93b..7891fc16822 100644 --- a/lib/tests/setuplib_test.php +++ b/lib/tests/setuplib_test.php @@ -398,4 +398,113 @@ class core_setuplib_testcase extends advanced_testcase { // Prove that we cannot use array_merge_recursive() instead. $this->assertNotSame($expected, array_merge_recursive($original, $chunk)); } + + /** + * Test the link processed by get_exception_info(). + */ + public function test_get_exception_info_link() { + global $CFG, $SESSION; + + $initialloginhttps = $CFG->loginhttps; + $httpswwwroot = str_replace('http:', 'https:', $CFG->wwwroot); + $CFG->loginhttps = false; + + // Simple local URL. + $url = $CFG->wwwroot . '/something/here?really=yes'; + $exception = new moodle_exception('none', 'error', $url); + $infos = $this->get_exception_info($exception); + $this->assertSame($url, $infos->link); + + // Relative local URL. + $url = '/something/here?really=yes'; + $exception = new moodle_exception('none', 'error', $url); + $infos = $this->get_exception_info($exception); + $this->assertSame($CFG->wwwroot . '/', $infos->link); + + // HTTPS URL when login HTTPS is not enabled. + $url = $httpswwwroot . '/something/here?really=yes'; + $exception = new moodle_exception('none', 'error', $url); + $infos = $this->get_exception_info($exception); + $this->assertSame($CFG->wwwroot . '/', $infos->link); + + // HTTPS URL with login HTTPS. + $CFG->loginhttps = true; + $url = $httpswwwroot . '/something/here?really=yes'; + $exception = new moodle_exception('none', 'error', $url); + $infos = $this->get_exception_info($exception); + $this->assertSame($url, $infos->link); + + // External HTTP URL. + $url = 'http://moodle.org/something/here?really=yes'; + $exception = new moodle_exception('none', 'error', $url); + $infos = $this->get_exception_info($exception); + $this->assertSame($CFG->wwwroot . '/', $infos->link); + + // External HTTPS URL. + $url = 'https://moodle.org/something/here?really=yes'; + $exception = new moodle_exception('none', 'error', $url); + $infos = $this->get_exception_info($exception); + $this->assertSame($CFG->wwwroot . '/', $infos->link); + + // External URL containing local URL. + $url = 'http://moodle.org/something/here?' . $CFG->wwwroot; + $exception = new moodle_exception('none', 'error', $url); + $infos = $this->get_exception_info($exception); + $this->assertSame($CFG->wwwroot . '/', $infos->link); + + // Internal link from fromurl. + $SESSION->fromurl = $url = $CFG->wwwroot . '/something/here?really=yes'; + $exception = new moodle_exception('none'); + $infos = $this->get_exception_info($exception); + $this->assertSame($url, $infos->link); + + // Internal HTTPS link from fromurl. + $SESSION->fromurl = $url = $httpswwwroot . '/something/here?really=yes'; + $exception = new moodle_exception('none'); + $infos = $this->get_exception_info($exception); + $this->assertSame($url, $infos->link); + + // Internal HTTPS link from fromurl without login HTTPS. + $CFG->loginhttps = false; + $SESSION->fromurl = $httpswwwroot . '/something/here?really=yes'; + $exception = new moodle_exception('none'); + $infos = $this->get_exception_info($exception); + $this->assertSame($CFG->wwwroot . '/', $infos->link); + + // External link from fromurl. + $SESSION->fromurl = 'http://moodle.org/something/here?really=yes'; + $exception = new moodle_exception('none'); + $infos = $this->get_exception_info($exception); + $this->assertSame($CFG->wwwroot . '/', $infos->link); + + // External HTTPS link from fromurl. + $SESSION->fromurl = 'https://moodle.org/something/here?really=yes'; + $exception = new moodle_exception('none'); + $infos = $this->get_exception_info($exception); + $this->assertSame($CFG->wwwroot . '/', $infos->link); + + // External HTTPS link from fromurl with login HTTPS. + $CFG->loginhttps = true; + $SESSION->fromurl = 'https://moodle.org/something/here?really=yes'; + $exception = new moodle_exception('none'); + $infos = $this->get_exception_info($exception); + $this->assertSame($CFG->wwwroot . '/', $infos->link); + + $CFG->loginhttps = $initialloginhttps; + $SESSION->fromurl = ''; + } + + /** + * Wrapper to call {@link get_exception_info()}. + * + * @param Exception $ex An exception. + * @return stdClass of information. + */ + public function get_exception_info($ex) { + try { + throw $ex; + } catch (moodle_exception $e) { + return get_exception_info($e); + } + } }