MDL-83332 core: Revert the slashargument removal on MDL-62640

Removing the option causes issues on MacOS.
This commit is contained in:
meirzamoodle 2024-10-02 18:24:42 +07:00
parent 0eacab846e
commit 3229dda3d6
38 changed files with 833 additions and 549 deletions

View File

@ -1,8 +0,0 @@
issueNumber: MDL-62640
notes:
core_admin:
- message: >-
The HTTP Server setting "Use slash arguments" (slasharguments) configuration setting and related
to it has been removed. Calling the option with $CFG->slasharguments or
get_config('slasharguments') is no longer available.
type: removed

View File

@ -1,9 +0,0 @@
issueNumber: MDL-62640
notes:
core:
- message: |
The code that is associated with the slashargument option has been deprecated. Here is the detail:
- The parameter $support of the \url::set_slashargument().
- The parameter $includeslashargument of the \url::get_path().
- The $CFG->yuislasharguments configuration.
type: deprecated

View File

@ -1,7 +0,0 @@
issueNumber: MDL-62640
notes:
core:
- message: |
Due to the removal of the slashargument configuration, the server check page will no longer inspect the slash argument,
therefore, the function check_slasharguments() is deprecated because it is no longer used.
type: deprecated

View File

@ -4634,6 +4634,11 @@
<ON_ERROR message="quizattemptsupgradedmessage" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_slasharguments" level="optional">
<FEEDBACK>
<ON_CHECK message="slashargumentswarning" />
</FEEDBACK>
</CUSTOM_CHECK>
<CUSTOM_CHECK file="lib/upgradelib.php" function="check_database_tables_row_format" level="optional">
<FEEDBACK>
<ON_CHECK message="unsupporteddbtablerowformat" />

View File

@ -150,6 +150,8 @@ if ($hassiteconfig) {
// HTTP.
$temp = new admin_settingpage('http', new lang_string('http', 'admin'));
$temp->add(new admin_setting_configcheckbox('slasharguments', new lang_string('slasharguments', 'admin'),
new lang_string('configslasharguments', 'admin'), 1));
$temp->add(new admin_setting_heading('reverseproxy', new lang_string('reverseproxy', 'admin'), '', ''));
$options = [
0 => 'HTTP_CLIENT_IP, HTTP_X_FORWARDED_FOR, REMOTE_ADDR',

View File

@ -63,8 +63,13 @@ class restore_structure_parser_processor extends grouped_parser_processor {
if (strpos($cdata, '$@FILEPHP@$') !== false) {
// We need to convert $@FILEPHP@$.
$slash = '/';
$forcedownload = '?forcedownload=1';
if ($CFG->slasharguments) {
$slash = '/';
$forcedownload = '?forcedownload=1';
} else {
$slash = '%2F';
$forcedownload = '&amp;forcedownload=1';
}
// We have to remove trailing slashes, otherwise file URLs will be restored with an extra slash.
$basefileurl = rtrim(moodle_url::make_legacyfile_url($this->courseid, null)->out(true), $slash);

View File

@ -23,8 +23,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_backup;
defined('MOODLE_INTERNAL') || die();
global $CFG;
@ -38,9 +36,8 @@ require_once($CFG->dirroot . '/backup/util/helper/restore_structure_parser_proce
* @package core_backup
* @copyright 2017 Dmitrii Metelkin (dmitriim@catalyst-au.net)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \core_backup\restore_structure_parser_processor
*/
final class restore_structure_parser_processor_test extends \advanced_testcase {
class restore_structure_parser_processor_test extends advanced_testcase {
/**
* Initial set up.
@ -57,52 +54,83 @@ final class restore_structure_parser_processor_test extends \advanced_testcase {
* @return array
*/
public function process_cdata_data_provider() {
return [
[null, null],
["$@NULL@$", null],
["$@NULL@$ ", "$@NULL@$ "],
[1, 1],
[" ", " "],
["1", "1"],
["$@FILEPHP@$1.jpg", "$@FILEPHP@$1.jpg"],
[
return array(
array(null, null, true),
array("$@NULL@$", null, true),
array("$@NULL@$ ", "$@NULL@$ ", true),
array(1, 1, true),
array(" ", " ", true),
array("1", "1", true),
array("$@FILEPHP@$1.jpg", "$@FILEPHP@$1.jpg", true),
array(
"http://test.test/$@SLASH@$",
"http://test.test/$@SLASH@$",
],
[
true
),
array(
"<a href='$@FILEPHP@$1.jpg'>Image</a>",
"<a href='http://test.test/file.php/11.jpg'>Image</a>",
],
[
true
),
array(
"<a href='$@FILEPHP@$$@SLASH@$1.jpg'>Image</a>",
"<a href='http://test.test/file.php/1/1.jpg'>Image</a>",
],
[
true
),
array(
"<a href='$@FILEPHP@$$@SLASH@$$@SLASH@$1.jpg'>Image</a>",
"<a href='http://test.test/file.php/1//1.jpg'>Image</a>",
],
[
true
),
array(
"<a href='$@FILEPHP@$1.jpg'>Image</a>",
"<a href='http://test.test/file.php?file=%2F11.jpg'>Image</a>",
false
),
array(
"<a href='$@FILEPHP@$$@SLASH@$1.jpg'>Image</a>",
"<a href='http://test.test/file.php?file=%2F1%2F1.jpg'>Image</a>",
false
),
array(
"<a href='$@FILEPHP@$$@SLASH@$$@SLASH@$1.jpg'>Image</a>",
"<a href='http://test.test/file.php?file=%2F1%2F%2F1.jpg'>Image</a>",
false
),
array(
"<a href='$@FILEPHP@$$@SLASH@$1.jpg$@FORCEDOWNLOAD@$'>Image</a>",
"<a href='http://test.test/file.php/1/1.jpg?forcedownload=1'>Image</a>",
],
[
true
),
array(
"<a href='$@FILEPHP@$$@SLASH@$1.jpg$@FORCEDOWNLOAD@$'>Image</a>",
"<a href='http://test.test/file.php?file=%2F1%2F1.jpg&amp;forcedownload=1'>Image</a>",
false
),
array(
"<iframe src='$@H5PEMBED@$?url=testurl'></iframe>",
"<iframe src='http://test.test/h5p/embed.php?url=testurl'></iframe>",
],
];
true
),
);
}
/**
* Test that restore_structure_parser_processor replaces $@FILEPHP@$ to correct file php links.
*
* @dataProvider process_cdata_data_provider
* @param mixed $content Testing content.
* @param mixed $expected Expected result.
* @param string $content Testing content.
* @param string $expected Expected result.
* @param bool $slasharguments A value for $CFG->slasharguments setting.
*/
public function test_process_cdata(mixed $content, mixed $expected): void {
public function test_process_cdata($content, $expected, $slasharguments): void {
global $CFG;
$CFG->slasharguments = $slasharguments;
$CFG->wwwroot = 'http://test.test';
$processor = new \restore_structure_parser_processor(1, 1);
$processor = new restore_structure_parser_processor(1, 1);
$this->assertEquals($expected, $processor->process_cdata($content));
}

View File

@ -329,6 +329,12 @@ $CFG->admin = 'admin';
// Please note: It is *not* possible to use X-Sendfile with the per-request directory.
// The directory is highly likely to have been deleted by the time the web server sends the file.
//
// YUI caching may be sometimes improved by slasharguments:
// $CFG->yuislasharguments = 1;
// Some servers may need a special rewrite rule to work around internal path length limitations:
// RewriteRule (^.*/theme/yui_combo\.php)(/.*) $1?file=$2
//
//
// Following settings may be used to select session driver, uncomment only one of the handlers.
// Database session handler:
// $CFG->session_handler_class = '\core\session\database';

View File

@ -450,26 +450,58 @@ class helper {
/**
* Returns the url to the cartridge representing the tool.
*
* If you have slash arguments enabled, this will be a nice url ending in cartridge.xml.
* If not it will be a php page with some parameters passed.
*
* @param \stdClass $tool The lti tool
* @return string The url to the cartridge representing the tool
* @since Moodle 3.2
*/
public static function get_cartridge_url($tool) {
global $CFG;
$url = null;
$id = $tool->id;
$token = self::generate_cartridge_token($tool->id);
return new \moodle_url('/enrol/lti/cartridge.php/' . $id . '/' . $token . '/cartridge.xml');
if ($CFG->slasharguments) {
$url = new \moodle_url('/enrol/lti/cartridge.php/' . $id . '/' . $token . '/cartridge.xml');
} else {
$url = new \moodle_url('/enrol/lti/cartridge.php',
array(
'id' => $id,
'token' => $token
)
);
}
return $url;
}
/**
* Returns the url to the tool proxy registration url.
*
* If you have slash arguments enabled, this will be a nice url ending in cartridge.xml.
* If not it will be a php page with some parameters passed.
*
* @param \stdClass $tool The lti tool
* @return string The url to the cartridge representing the tool
*/
public static function get_proxy_url($tool) {
global $CFG;
$url = null;
$id = $tool->id;
$token = self::generate_proxy_token($tool->id);
return new \moodle_url('/enrol/lti/proxy.php/' . $id . '/' . $token . '/');
if ($CFG->slasharguments) {
$url = new \moodle_url('/enrol/lti/proxy.php/' . $id . '/' . $token . '/');
} else {
$url = new \moodle_url('/enrol/lti/proxy.php',
array(
'id' => $id,
'token' => $token
)
);
}
return $url;
}
/**

View File

@ -22,8 +22,6 @@ namespace enrol_lti;
* @package enrol_lti
* @copyright 2016 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*
* @covers \enrol_lti\helper
*/
class helper_test extends \advanced_testcase {
@ -262,6 +260,12 @@ class helper_test extends \advanced_testcase {
* Test getting the cartridge url of a tool.
*/
public function test_get_cartridge_url(): void {
global $CFG;
$slasharguments = $CFG->slasharguments;
$CFG->slasharguments = false;
$course1 = $this->getDataGenerator()->create_course();
$data = new \stdClass();
$data->courseid = $course1->id;
@ -269,16 +273,29 @@ class helper_test extends \advanced_testcase {
$id = $tool1->id;
$token = \enrol_lti\helper::generate_cartridge_token($id);
/** @var \moodle_url $launchurl */
$launchurl = \enrol_lti\helper::get_cartridge_url($tool1);
$this->assertEquals('https://www.example.com/moodle/enrol/lti/cartridge.php?id=' . $id . '&amp;token=' . $token,
$launchurl->out());
$CFG->slasharguments = true;
$launchurl = \enrol_lti\helper::get_cartridge_url($tool1);
$this->assertEquals('https://www.example.com/moodle/enrol/lti/cartridge.php/' . $id . '/' . $token . '/cartridge.xml',
$launchurl->out());
$CFG->slasharguments = $slasharguments;
}
/**
* Test getting the cartridge url of a tool.
*/
public function test_get_proxy_url(): void {
global $CFG;
$slasharguments = $CFG->slasharguments;
$CFG->slasharguments = false;
$course1 = $this->getDataGenerator()->create_course();
$data = new \stdClass();
$data->courseid = $course1->id;
@ -286,10 +303,17 @@ class helper_test extends \advanced_testcase {
$id = $tool1->id;
$token = \enrol_lti\helper::generate_proxy_token($id);
/** @var \moodle_url $launchurl */
$launchurl = \enrol_lti\helper::get_proxy_url($tool1);
$this->assertEquals('https://www.example.com/moodle/enrol/lti/proxy.php?id=' . $id . '&amp;token=' . $token,
$launchurl->out());
$CFG->slasharguments = true;
$launchurl = \enrol_lti\helper::get_proxy_url($tool1);
$this->assertEquals('https://www.example.com/moodle/enrol/lti/proxy.php/' . $id . '/' . $token . '/',
$launchurl->out());
$CFG->slasharguments = $slasharguments;
}
/**

View File

@ -1,241 +1,198 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
// This function fetches math. images from the data directory
// If not, it obtains the corresponding TeX expression from the cache_tex db table
// and uses mimeTeX to create the image file
/**
* Debug algebra filter.
*
* @package filter_algebra
* @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once("../../config.php");
require_once("../../config.php");
if (!filter_is_enabled('algebra')) {
throw new \moodle_exception('filternotenabled');
}
require_once($CFG->libdir.'/filelib.php');
require_once($CFG->dirroot.'/filter/tex/lib.php');
$action = optional_param('action', '', PARAM_ALPHANUM);
$algebra = optional_param('algebra', '', PARAM_RAW);
require_login();
require_capability('moodle/site:config', context_system::instance());
if ($action || $algebra) {
require_sesskey();
}
if ($algebra && $action) {
$md5 = md5($algebra);
if ($action === 'ShowDB' || $action === 'DeleteDB') {
$texcache = $DB->get_record("cache_filters", ["filter" => "algebra", "md5key" => $md5]);
if (!filter_is_enabled('algebra')) {
throw new \moodle_exception('filternotenabled');
}
if ($action === 'ShowDB') {
require_once($CFG->libdir.'/filelib.php');
require_once($CFG->dirroot.'/filter/tex/lib.php');
$action = optional_param('action', '', PARAM_ALPHANUM);
$algebra = optional_param('algebra', '', PARAM_RAW);
require_login();
require_capability('moodle/site:config', context_system::instance());
if ($action || $algebra) {
require_sesskey();
}
if ($algebra && $action) {
$md5 = md5($algebra);
if ($action == 'ShowDB' || $action == 'DeleteDB') {
$texcache = $DB->get_record("cache_filters", array("filter"=>"algebra", "md5key"=>$md5));
}
if ($action == 'ShowDB') {
if ($texcache) {
$output = "DB cache_filters entry for $algebra\n";
$output .= "id = $texcache->id\n";
$output .= "filter = $texcache->filter\n";
$output .= "version = $texcache->version\n";
$output .= "md5key = $texcache->md5key\n";
$output .= "rawtext = $texcache->rawtext\n";
$output .= "timemodified = $texcache->timemodified\n";
$output = "DB cache_filters entry for $algebra\n";
$output .= "id = $texcache->id\n";
$output .= "filter = $texcache->filter\n";
$output .= "version = $texcache->version\n";
$output .= "md5key = $texcache->md5key\n";
$output .= "rawtext = $texcache->rawtext\n";
$output .= "timemodified = $texcache->timemodified\n";
} else {
$output = "DB cache_filters entry for $algebra not found\n";
$output = "DB cache_filters entry for $algebra not found\n";
}
}
if ($action === 'DeleteDB') {
}
if ($action == 'DeleteDB') {
if ($texcache) {
$output = "Deleting DB cache_filters entry for $algebra\n";
$result = $DB->delete_records("cache_filters", ["id" => $texcache->id]);
if ($result) {
$result = 1;
} else {
$result = 0;
}
$output .= "Number of records deleted = $result\n";
$output = "Deleting DB cache_filters entry for $algebra\n";
$result = $DB->delete_records("cache_filters", array("id"=>$texcache->id));
if ($result) {
$result = 1;
} else {
$result = 0;
}
$output .= "Number of records deleted = $result\n";
} else {
$output = "Could not delete DB cache_filters entry for $algebra\nbecause it could not be found.\n";
$output = "Could not delete DB cache_filters entry for $algebra\nbecause it could not be found.\n";
}
}
if ($action === 'TeXStage1') {
}
if ($action == 'TeXStage1') {
$output = algebra2tex($algebra);
}
if ($action === 'TexStage2') {
}
if ($action == 'TexStage2') {
$output = algebra2tex($algebra);
$output = refineTeX($output);
}
if ($action === 'ShowImage') {
}
if ($action == 'ShowImage'|| $action == 'SlashArguments') {
$output = algebra2tex($algebra);
$output = refineTeX($output);
tex2image($output, $md5);
} else {
if ($action == 'ShowImage') {
tex2image($output, $md5);
} else {
slasharguments($output, $md5);
}
} else {
outputText($output);
}
exit;
}
exit;
}
function algebra2tex($algebra) {
global $CFG;
$algebra = str_replace('&lt;', '<', $algebra);
$algebra = str_replace('&gt;', '>', $algebra);
$algebra = str_replace('<>', '#', $algebra);
$algebra = str_replace('<=', '%', $algebra);
$algebra = str_replace('>=', '!', $algebra);
$algebra = preg_replace('/([=><%!#] *)-/', "\$1 zeroplace -", $algebra);
$algebra = str_replace('delta', 'zdelta', $algebra);
$algebra = str_replace('beta', 'bita', $algebra);
$algebra = str_replace('theta', 'thita', $algebra);
$algebra = str_replace('zeta', 'zita', $algebra);
$algebra = str_replace('eta', 'xeta', $algebra);
$algebra = str_replace('epsilon', 'zepslon', $algebra);
$algebra = str_replace('upsilon', 'zupslon', $algebra);
$algebra = preg_replace('!\r\n?!', ' ', $algebra);
$algebra = escapeshellarg($algebra);
global $CFG;
$algebra = str_replace('&lt;','<',$algebra);
$algebra = str_replace('&gt;','>',$algebra);
$algebra = str_replace('<>','#',$algebra);
$algebra = str_replace('<=','%',$algebra);
$algebra = str_replace('>=','!',$algebra);
$algebra = preg_replace('/([=><%!#] *)-/',"\$1 zeroplace -",$algebra);
$algebra = str_replace('delta','zdelta',$algebra);
$algebra = str_replace('beta','bita',$algebra);
$algebra = str_replace('theta','thita',$algebra);
$algebra = str_replace('zeta','zita',$algebra);
$algebra = str_replace('eta','xeta',$algebra);
$algebra = str_replace('epsilon','zepslon',$algebra);
$algebra = str_replace('upsilon','zupslon',$algebra);
$algebra = preg_replace('!\r\n?!',' ',$algebra);
$algebra = escapeshellarg($algebra);
if ( (PHP_OS === "WINNT") || (PHP_OS === "WIN32") || (PHP_OS === "Windows") ) {
$cmd = "cd $CFG->dirroot\\filter\\algebra & algebra2tex.pl x/2";
$test = shell_exec("\$cmd");
if ($test !== '\frac{x}{2}') {
echo "There is a problem with either Perl or the script algebra2tex.pl<br/>";
$ecmd = $cmd . " 2>&1";
echo shell_exec("\$ecmd") . "<br/>\n";
echo "The shell command<br/>$cmd<br/>returned status = $status<br/>\n";
$commandpath = "$CFG->dirroot\\filter\\algebra\\algebra2tex.pl";
if (file_exists($commandpath)) {
echo "The file permissions of algebra2tex.pl are: " . decoct(fileperms($commandpath)) . "<br/>";
}
die;
}
$cmd = "cd $CFG->dirroot\\filter\\algebra & algebra2tex.pl $algebra";
} else {
$cmd = "cd $CFG->dirroot/filter/algebra; ./algebra2tex.pl x/2";
$test = shell_exec("\$cmd");
if ($test !== '\frac{x}{2}') {
echo "There is a problem with either Perl or the script algebra2tex.pl<br/>";
$ecmd = $cmd . " 2>&1";
echo shell_exec("\$ecmd") . "<br/>\n";
echo "The shell command<br/>$cmd<br/>returned status = $status<br/>\n";
$commandpath = "$CFG->dirroot/filter/algebra/algebra2tex.pl";
if (file_exists($commandpath)) {
echo "The file permissions of algebra2tex.pl are: " . decoct(fileperms($commandpath)) . "<br/>";
}
die;
}
$cmd = "cd $CFG->dirroot/filter/algebra; ./algebra2tex.pl $algebra";
if ( (PHP_OS == "WINNT") || (PHP_OS == "WIN32") || (PHP_OS == "Windows") ) {
$cmd = "cd $CFG->dirroot\\filter\\algebra & algebra2tex.pl x/2";
$test = `$cmd`;
if ($test != '\frac{x}{2}') {
echo "There is a problem with either Perl or the script algebra2tex.pl<br/>";
$ecmd = $cmd . " 2>&1";
echo `$ecmd` . "<br/>\n";
echo "The shell command<br/>$cmd<br/>returned status = $status<br/>\n";
$commandpath = "$CFG->dirroot\\filter\\algebra\\algebra2tex.pl";
if (file_exists($commandpath)) {
echo "The file permissions of algebra2tex.pl are: " . decoct(fileperms($commandpath)) . "<br/>";
}
die;
}
$texexp = shell_exec("\$cmd");
return $texexp;
$cmd = "cd $CFG->dirroot\\filter\\algebra & algebra2tex.pl $algebra";
} else {
$cmd = "cd $CFG->dirroot/filter/algebra; ./algebra2tex.pl x/2";
$test = `$cmd`;
if ($test != '\frac{x}{2}') {
echo "There is a problem with either Perl or the script algebra2tex.pl<br/>";
$ecmd = $cmd . " 2>&1";
echo `$ecmd` . "<br/>\n";
echo "The shell command<br/>$cmd<br/>returned status = $status<br/>\n";
$commandpath = "$CFG->dirroot/filter/algebra/algebra2tex.pl";
if (file_exists($commandpath)) {
echo "The file permissions of algebra2tex.pl are: " . decoct(fileperms($commandpath)) . "<br/>";
}
die;
}
$cmd = "cd $CFG->dirroot/filter/algebra; ./algebra2tex.pl $algebra";
}
$texexp = `$cmd`;
return $texexp;
}
function refineTeX($texexp) {
$texexp = str_replace('zeroplace', '', $texexp);
$texexp = str_replace('#', '\not= ', $texexp);
$texexp = str_replace('%', '\leq ', $texexp);
$texexp = str_replace('!', '\geq ', $texexp);
$texexp = str_replace('\left{', '{', $texexp);
$texexp = str_replace('\right}', '}', $texexp);
$texexp = str_replace('\fun', ' ', $texexp);
$texexp = str_replace('infty', '\infty', $texexp);
$texexp = str_replace('alpha', '\alpha', $texexp);
$texexp = str_replace('gamma', '\gamma', $texexp);
$texexp = str_replace('iota', '\iota', $texexp);
$texexp = str_replace('kappa', '\kappa', $texexp);
$texexp = str_replace('lambda', '\lambda', $texexp);
$texexp = str_replace('mu', '\mu', $texexp);
$texexp = str_replace('nu', '\nu', $texexp);
$texexp = str_replace('xi', '\xi', $texexp);
$texexp = str_replace('rho', '\rho', $texexp);
$texexp = str_replace('sigma', '\sigma', $texexp);
$texexp = str_replace('tau', '\tau', $texexp);
$texexp = str_replace('phi', '\phi', $texexp);
$texexp = str_replace('chi', '\chi', $texexp);
$texexp = str_replace('psi', '\psi', $texexp);
$texexp = str_replace('omega', '\omega', $texexp);
$texexp = str_replace('zdelta', '\delta', $texexp);
$texexp = str_replace('bita', '\beta', $texexp);
$texexp = str_replace('thita', '\theta', $texexp);
$texexp = str_replace('zita', '\zeta', $texexp);
$texexp = str_replace('xeta', '\eta', $texexp);
$texexp = str_replace('zepslon', '\epsilon', $texexp);
$texexp = str_replace('zupslon', '\upsilon', $texexp);
$texexp = str_replace('\mbox{logten}', '\mbox{log}_{10}', $texexp);
$texexp = str_replace('\mbox{acos}', '\mbox{cos}^{-1}', $texexp);
$texexp = str_replace('\mbox{asin}', '\mbox{sin}^{-1}', $texexp);
$texexp = str_replace('\mbox{atan}', '\mbox{tan}^{-1}', $texexp);
$texexp = str_replace('\mbox{asec}', '\mbox{sec}^{-1}', $texexp);
$texexp = str_replace('\mbox{acsc}', '\mbox{csc}^{-1}', $texexp);
$texexp = str_replace('\mbox{acot}', '\mbox{cot}^{-1}', $texexp);
$texexp = str_replace('\mbox{acosh}', '\mbox{cosh}^{-1}', $texexp);
$texexp = str_replace('\mbox{asinh}', '\mbox{sinh}^{-1}', $texexp);
$texexp = str_replace('\mbox{atanh}', '\mbox{tanh}^{-1}', $texexp);
$texexp = str_replace('\mbox{asech}', '\mbox{sech}^{-1}', $texexp);
$texexp = str_replace('\mbox{acsch}', '\mbox{csch}^{-1}', $texexp);
$texexp = str_replace('\mbox{acoth}', '\mbox{coth}^{-1}', $texexp);
$texexp = preg_replace(
'/\\\sqrt{(.+?),(.+?)}/s',
'\sqrt[' . "\$2]{\$1}",
$texexp,
);
$texexp = preg_replace(
'/\\\mbox{abs}\\\left\((.+?)\\\right\)/s',
"|\$1|",
$texexp,
);
$texexp = preg_replace(
'/\\\log\\\left\((.+?),(.+?)\\\right\)/s',
'\log_{'. "\$2}\\left(\$1\\right)",
$texexp,
);
$texexp = preg_replace(
'/(\\\cos|\\\sin|\\\tan|\\\sec|\\\csc|\\\cot)([h]*)\\\left\((.+?),(.+?)\\\right\)/s',
"\$1\$2^{". "\$4}\\left(\$3\\right)",
$texexp,
);
$texexp = preg_replace(
'/\\\int\\\left\((.+?),(.+?),(.+?)\\\right\)/s',
'\int_'. "{\$2}^{\$3}\$1 ",
$texexp,
);
$texexp = preg_replace(
'/\\\int\\\left\((.+?d[a-z])\\\right\)/s',
'\int ' . "\$1 ",
$texexp,
);
$texexp = preg_replace(
'/\\\lim\\\left\((.+?),(.+?),(.+?)\\\right\)/s',
'\lim_' . "{\$2\\to \$3}\$1 ",
$texexp,
);
return $texexp;
$texexp = str_replace('zeroplace','',$texexp);
$texexp = str_replace('#','\not= ',$texexp);
$texexp = str_replace('%','\leq ',$texexp);
$texexp = str_replace('!','\geq ',$texexp);
$texexp = str_replace('\left{','{',$texexp);
$texexp = str_replace('\right}','}',$texexp);
$texexp = str_replace('\fun',' ',$texexp);
$texexp = str_replace('infty','\infty',$texexp);
$texexp = str_replace('alpha','\alpha',$texexp);
$texexp = str_replace('gamma','\gamma',$texexp);
$texexp = str_replace('iota','\iota',$texexp);
$texexp = str_replace('kappa','\kappa',$texexp);
$texexp = str_replace('lambda','\lambda',$texexp);
$texexp = str_replace('mu','\mu',$texexp);
$texexp = str_replace('nu','\nu',$texexp);
$texexp = str_replace('xi','\xi',$texexp);
$texexp = str_replace('rho','\rho',$texexp);
$texexp = str_replace('sigma','\sigma',$texexp);
$texexp = str_replace('tau','\tau',$texexp);
$texexp = str_replace('phi','\phi',$texexp);
$texexp = str_replace('chi','\chi',$texexp);
$texexp = str_replace('psi','\psi',$texexp);
$texexp = str_replace('omega','\omega',$texexp);
$texexp = str_replace('zdelta','\delta',$texexp);
$texexp = str_replace('bita','\beta',$texexp);
$texexp = str_replace('thita','\theta',$texexp);
$texexp = str_replace('zita','\zeta',$texexp);
$texexp = str_replace('xeta','\eta',$texexp);
$texexp = str_replace('zepslon','\epsilon',$texexp);
$texexp = str_replace('zupslon','\upsilon',$texexp);
$texexp = str_replace('\mbox{logten}','\mbox{log}_{10}',$texexp);
$texexp = str_replace('\mbox{acos}','\mbox{cos}^{-1}',$texexp);
$texexp = str_replace('\mbox{asin}','\mbox{sin}^{-1}',$texexp);
$texexp = str_replace('\mbox{atan}','\mbox{tan}^{-1}',$texexp);
$texexp = str_replace('\mbox{asec}','\mbox{sec}^{-1}',$texexp);
$texexp = str_replace('\mbox{acsc}','\mbox{csc}^{-1}',$texexp);
$texexp = str_replace('\mbox{acot}','\mbox{cot}^{-1}',$texexp);
$texexp = str_replace('\mbox{acosh}','\mbox{cosh}^{-1}',$texexp);
$texexp = str_replace('\mbox{asinh}','\mbox{sinh}^{-1}',$texexp);
$texexp = str_replace('\mbox{atanh}','\mbox{tanh}^{-1}',$texexp);
$texexp = str_replace('\mbox{asech}','\mbox{sech}^{-1}',$texexp);
$texexp = str_replace('\mbox{acsch}','\mbox{csch}^{-1}',$texexp);
$texexp = str_replace('\mbox{acoth}','\mbox{coth}^{-1}',$texexp);
$texexp = preg_replace('/\\\sqrt{(.+?),(.+?)}/s','\sqrt['. "\$2]{\$1}",$texexp);
$texexp = preg_replace('/\\\mbox{abs}\\\left\((.+?)\\\right\)/s',"|\$1|",$texexp);
$texexp = preg_replace('/\\\log\\\left\((.+?),(.+?)\\\right\)/s','\log_{'. "\$2}\\left(\$1\\right)",$texexp);
$texexp = preg_replace('/(\\\cos|\\\sin|\\\tan|\\\sec|\\\csc|\\\cot)([h]*)\\\left\((.+?),(.+?)\\\right\)/s',"\$1\$2^{". "\$4}\\left(\$3\\right)",$texexp);
$texexp = preg_replace('/\\\int\\\left\((.+?),(.+?),(.+?)\\\right\)/s','\int_'. "{\$2}^{\$3}\$1 ",$texexp);
$texexp = preg_replace('/\\\int\\\left\((.+?d[a-z])\\\right\)/s','\int '. "\$1 ",$texexp);
$texexp = preg_replace('/\\\lim\\\left\((.+?),(.+?),(.+?)\\\right\)/s','\lim_'. "{\$2\\to \$3}\$1 ",$texexp);
return $texexp;
}
function outputText($texexp) {
header("Content-type: text/html; charset=utf-8");
echo "<html><body><pre>\n";
if ($texexp) {
$texexp = str_replace('<', '&lt;', $texexp);
$texexp = str_replace('>', '&gt;', $texexp);
$texexp = str_replace('"', '&quot;', $texexp);
echo "$texexp\n\n";
} else {
echo "No text output available\n\n";
}
echo "</pre></body></html>\n";
header("Content-type: text/html; charset=utf-8");
echo "<html><body><pre>\n";
if ($texexp) {
$texexp = str_replace('<','&lt;',$texexp);
$texexp = str_replace('>','&gt;',$texexp);
$texexp = str_replace('"','&quot;',$texexp);
echo "$texexp\n\n";
} else {
echo "No text output available\n\n";
}
echo "</pre></body></html>\n";
}
function tex2image($texexp, $md5, $return=false) {
@ -295,75 +252,94 @@ function tex2image($texexp, $md5, $return=false) {
}
}
function slasharguments($texexp, $md5) {
global $CFG;
$admin = $CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=http';
$image = tex2image($texexp,$md5,true);
echo "<p>If the following image displays correctly, set your ";
echo "<a href=\"$admin\" target=\"_blank\">Administration->Server->HTTP</a> ";
echo "setting for slasharguments to file.php/1/pic.jpg: ";
echo "<img src=\"pix.php/$image\" align=\"absmiddle\"></p>\n";
echo "<p>Otherwise set it to file.php?file=/1/pic.jpg ";
echo "It should display correctly as ";
echo "<img src=\"pix.php?file=$image\" align=\"absmiddle\"></p>\n";
echo "<p>If neither equation image displays correctly, please seek ";
echo "further help at moodle.org at the ";
echo "<a href=\"http://moodle.org/mod/forum/view.php?id=752&loginguest=true\" target=\"_blank\">";
echo "Mathematics Tools Forum</a></p>";
}
?>
<html>
<head><title>Algebra Filter Debugger</title></head>
<body>
<p>Please enter an algebraic expression <b>without</b> any surrounding @@ into
the text box below. (Click <a href="#help">here for help.</a>)
<form action="algebradebug.php" method="get"
target="inlineframe">
<center>
<label for="algebra" class="accesshide"><?php print_string('algebraicexpression', 'filter_algebra'); ?></label>
<input type="text" id="algebra" name="algebra" size="50"
value="sin(z)/(x^2+y^2)" />
</center>
<ol>
<li>First click on this button <button type="submit" name="action" value="ShowDB">Show DB Entry</button>
to see the cache_filters database entry for this expression.</li>
<li>If the database entry looks corrupt, click on this button to delete it:
<button type="submit" name="action" value="DeleteDB">Delete DB Entry</button></li>
<li>Now click on this button <button type="submit" name="action" value="TeXStage1">First Stage Tex Translation</button>.
A preliminary translation into TeX will appear in the box below.</li>
<li>Next click on this button <button type="submit" name="action" value="TexStage2">Second Stage Tex Translation</button>.
A more refined translation into TeX will appear in the box below.</li>
<li>Then click on this button <button type="submit" name="action" value="ShowImage">Show Image</button>
to show a graphic image of the algebraic expression.</li>
</ol>
<input type="hidden" name="sesskey" value="<?php echo sesskey(); ?>" />
</form> <br /> <br />
<center>
<iframe name="inlineframe" align="middle" width="80%" height="200">
&lt;p&gt;Something is wrong...&lt;/p&gt;
</iframe>
</center> <br />
<p>Please enter an algebraic expression <b>without</b> any surrounding @@ into
the text box below. (Click <a href="#help">here for help.</a>)
<form action="algebradebug.php" method="get"
target="inlineframe">
<center>
<label for="algebra" class="accesshide"><?php print_string('algebraicexpression', 'filter_algebra'); ?></label>
<input type="text" id="algebra" name="algebra" size="50"
value="sin(z)/(x^2+y^2)" />
</center>
<ol>
<li>First click on this button <button type="submit" name="action" value="ShowDB">Show DB Entry</button>
to see the cache_filters database entry for this expression.</li>
<li>If the database entry looks corrupt, click on this button to delete it:
<button type="submit" name="action" value="DeleteDB">Delete DB Entry</button></li>
<li>Now click on this button <button type="submit" name="action" value="TeXStage1">First Stage Tex Translation</button>.
A preliminary translation into TeX will appear in the box below.</li>
<li>Next click on this button <button type="submit" name="action" value="TexStage2">Second Stage Tex Translation</button>.
A more refined translation into TeX will appear in the box below.</li>
<li>Then click on this button <button type="submit" name="action" value="ShowImage">Show Image</button>
to show a graphic image of the algebraic expression.</li>
<li>Finally check your slash arguments setting
<button type="submit" name="action" value="SlashArguments">Check Slash Arguments</button></li>
</ol>
<input type="hidden" name="sesskey" value="<?php echo sesskey(); ?>" />
</form> <br /> <br />
<center>
<iframe name="inlineframe" align="middle" width="80%" height="200">
&lt;p&gt;Something is wrong...&lt;/p&gt;
</iframe>
</center> <br />
<hr />
<a name="help">
<h2>Debugging Help</h2>
<h2>Debugging Help</h2>
</a>
<p>First here is a brief overview on how the algebra filter works. It
takes an algebra expression and first translates it into TeX. It first
looks for the TeX translation in the Moodle database in the table cache_filters
in the field rawtext. If not found, it passes the algebraic expression to the
Perl script algebra2tex.pl, which also uses the Perl library AlgParser.pm.
It then saves the TeX translation in the database for subsequent uses and
passes the TeX to the mimetex executable to be converted to a gif image.
Here are a few common things that can go wrong and some suggestions on how
you might try to fix them.</p>
takes an algebra expression and first translates it into TeX. It first
looks for the TeX translation in the Moodle database in the table cache_filters
in the field rawtext. If not found, it passes the algebraic expression to the
Perl script algebra2tex.pl, which also uses the Perl library AlgParser.pm.
It then saves the TeX translation in the database for subsequent uses and
passes the TeX to the mimetex executable to be converted to a gif image.
Here are a few common things that can go wrong and some suggestions on how
you might try to fix them.</p>
<ol>
<li>Something had gone wrong on a previous occasion when the filter tried to
translate this expression. Then the database entry for that expression contains
a bad TeX translation in the rawtext field (usually blank). You can fix this
by clicking on &quot;Delete DB Entry&quot;</li>
<li>The First Stage TeX Translation gives a &quot;No text output available&quot;
message. If your server is running Windows, this may be due to the fact that
you haven't installed Perl or didn't install it correctly. If your server is
running some version of Unix (e.g. Linux), then this may be due to your Perl
binary being installed in a nonstandard location. To fix this edit the first
line of the algebra2tex.pl script. Another possible problem which may affect
both Unix and Windows servers is that the web server doesn't have execute permission
on the algebra2tex.pl script. In that case change permissions accordingly</li>
<li>The Second Stage TeX Translation produces malformed TeX. This indicates
a bug in the algebra filter. Post the original algebraic expression and the
bad TeX translation in the <a href="http://moodle.org/mod/forum/view.php?id=752">
Mathematics Tools</a> forum in the Using Moodle course on moodle.org.</li>
<li>The TeX to gif image conversion process does not work. If your server is
running Unix, a likely cause is that the mimetex binary you are using is
incompatible with your operating system. You can try compiling it from the
C sources downloaded from <a href="http://www.forkosh.com/mimetex.zip">
http://www.forkosh.com/mimetex.zip</a>. Lastly check the execute permissions
on your mimetex binary, as outlined in item 2 above.</li>
<li>Something had gone wrong on a previous occasion when the filter tried to
translate this expression. Then the database entry for that expression contains
a bad TeX translation in the rawtext field (usually blank). You can fix this
by clicking on &quot;Delete DB Entry&quot;</li>
<li>The First Stage TeX Translation gives a &quot;No text output available&quot;
message. If your server is running Windows, this may be due to the fact that
you haven't installed Perl or didn't install it correctly. If your server is
running some version of Unix (e.g. Linux), then this may be due to your Perl
binary being installed in a nonstandard location. To fix this edit the first
line of the algebra2tex.pl script. Another possible problem which may affect
both Unix and Windows servers is that the web server doesn't have execute permission
on the algebra2tex.pl script. In that case change permissions accordingly</li>
<li>The Second Stage TeX Translation produces malformed TeX. This indicates
a bug in the algebra filter. Post the original algebraic expression and the
bad TeX translation in the <a href="http://moodle.org/mod/forum/view.php?id=752">
Mathematics Tools</a> forum in the Using Moodle course on moodle.org.</li>
<li>The TeX to gif image conversion process does not work. If your server is
running Unix, a likely cause is that the mimetex binary you are using is
incompatible with your operating system. You can try compiling it from the
C sources downloaded from <a href="http://www.forkosh.com/mimetex.zip">
http://www.forkosh.com/mimetex.zip</a>. Lastly check the execute permissions
on your mimetex binary, as outlined in item 2 above.</li>
</ol>
</body>
</html>

View File

@ -230,7 +230,12 @@ class text_filter extends \core_filters\text_filter {
$anchorcontents = '';
if ($imagefile) {
$anchorcontents .= "<img $title alt=\"" . s($tex) . "\" src=\"";
$anchorcontents .= "$CFG->wwwroot/filter/algebra/pix.php/$imagefile";
if ($CFG->slasharguments) {
// Use this method if possible for better caching.
$anchorcontents .= "$CFG->wwwroot/filter/algebra/pix.php/$imagefile";
} else {
$anchorcontents .= "$CFG->wwwroot/filter/algebra/pix.php?file=$imagefile";
}
$anchorcontents .= "\" $style />";
$imagefound = file_exists("$CFG->dataroot/filter/algebra/$imagefile");

View File

@ -186,7 +186,12 @@ class text_filter extends \core_filters\text_filter {
// Build the output.
$anchorcontents = "<img class=\"texrender\" $title alt=\"$alt\" src=\"";
$anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php/$imagefile";
if ($CFG->slasharguments) {
// Use this method if possible for better client-side caching.
$anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php/$imagefile";
} else {
$anchorcontents .= "$CFG->wwwroot/filter/tex/pix.php?file=$imagefile";
}
$anchorcontents .= "\" $style/>";
$imagefound = file_exists("$CFG->dataroot/filter/tex/$imagefile");

View File

@ -89,6 +89,12 @@
tex2image($texexp);
}
// Action: Check Slasharguments
if ($action=='SlashArguments') {
slasharguments($texexp);
exit;
}
// Action: Show Tex command line output
if ($action=='ShowImageTex') {
TexOutput($texexp, true);
@ -287,6 +293,23 @@
return $output;
}
function slasharguments($texexp) {
global $CFG;
$admin = $CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=http';
$image = tex2image($texexp,true);
echo "<p>If the following image displays correctly, set your ";
echo "<a href=\"$admin\" target=\"_blank\">Administration->Server->HTTP</a> ";
echo "setting for slasharguments to file.php/1/pic.jpg: ";
echo "<img src=\"$CFG->wwwroot/filter/tex/pix.php/$image\" align=\"absmiddle\"></p>\n";
echo "<p>Otherwise set it to file.php?file=/1/pic.jpg ";
echo "It should display correctly as ";
echo "<img src=\"$CFG->wwwroot/filter/tex/pix.php?file=$image\" align=\"absmiddle\"></p>\n";
echo "<p>If neither equation image displays correctly, please seek ";
echo "further help at moodle.org at the ";
echo "<a href=\"http://moodle.org/mod/forum/view.php?id=752&loginguest=true\" target=\"_blank\">";
echo "Mathematics Tools Forum</a></p>";
}
?>
<html>
@ -312,6 +335,8 @@
<label for="ShowImageTex">Show a graphic image of the algebraic expression rendered with Tex/Ghostscript.</label></li>
<li><input type="radio" name="action" value="ShowOutputTex" id="ShowOutputTex" />
<label for="ShowOutputTex">Show command execution output from the algebraic expression rendered with Tex/Ghostscript.</label></li>
<li><input type="radio" name="action" value="SlashArguments" id="SlashArguments" />
<label for="SlashArguments">Check slasharguments setting.</label></li>
</ol>
<input type="submit" value="Do it!" />
<input type="hidden" name="sesskey" value="<?php echo sesskey(); ?>" />

View File

@ -382,6 +382,7 @@ $string['configsitedefaultlicensehelp'] = 'The default licence for publishing co
$string['configsitemailcharset'] = 'This setting specifies the default charset for all emails sent from the site.';
$string['configsitemaxcategorydepth'] = 'Maximum category depth';
$string['configsitemaxcategorydepthhelp'] = 'This specifies the maximum depth of child categories expanded when displaying categories or combo list. Deeper level categories will appear as links and user can expand them with AJAX request.';
$string['configslasharguments'] = '\'Slash arguments\' (using <em>PATH_INFO</em>) is required for SCORM packages and multiple-file resources to display correctly. If your web server doesn\'t support \'slash arguments\' and you are unable to configure it, this setting can be disabled, though it will result in things not working.<br />Note: The use of \'slash arguments\' will be required in future versions of Moodle.';
$string['configsmtpauthtype'] = 'This sets the authentication type to use on SMTP server.';
$string['configsmtpoauthservice'] = 'Select the OAuth 2 service that is configured to talk to the SMTP server. If the service doesn\'t exist yet, you will need to create it. Note that you need to set the SMTP Auth Type to XOAUTH2.';
$string['configsmtphosts'] = 'Give the full name of one or more local SMTP servers that Moodle should use to send mail (eg \'mail.a.com\' or \'mail.a.com;mail.b.com\'). To specify a non-default port (i.e other than port 25), you can use the [server]:[port] syntax (eg \'mail.a.com:587\'). For secure connections, port 465 is usually used with SSL, port 587 is usually used with TLS, specify security protocol below if required. If you leave this field blank, Moodle will use the PHP default method of sending mail.';
@ -1310,6 +1311,8 @@ $string['sitepolicyguest_help'] = 'The URL of the site policy that all guests mu
$string['sitesectionhelp'] = 'Display a section at the top of the page where you can add custom content.';
$string['sixtyfourbitsrequired'] = 'It has been detected that your site is not using a 64-bit PHP version. You are required to upgrade your system (operating system, PHP...) before installing this Moodle version.';
$string['sixtyfourbitswarning'] = 'It has been detected that your site is not using a 64-bit PHP version. It is recommended that you upgrade your site to ensure future compatibility.';
$string['slasharguments'] = 'Use slash arguments';
$string['slashargumentswarning'] = 'It is recommended that the use of slash arguments is enabled. In future it will be required. For more details, see the documentation <a href="https://docs.moodle.org/en/admin/environment/slasharguments">Using slash arguments</a>.';
$string['smallscreensonly'] = 'Small screens only';
$string['smtp'] = 'SMTP';
$string['smtpauthtype'] = 'SMTP Auth Type';
@ -1656,11 +1659,8 @@ $string['moodleservices'] = 'Moodle services';
$string['moodleservices_help'] = 'Make sure you get the best from your Moodle learning environment by using these Moodle services:';
// Deprecated since Moodle 4.5.
$string['configslasharguments'] = '\'Slash arguments\' (using <em>PATH_INFO</em>) is required for SCORM packages and multiple-file resources to display correctly. If your web server doesn\'t support \'slash arguments\' and you are unable to configure it, this setting can be disabled, though it will result in things not working.<br />Note: The use of \'slash arguments\' will be required in future versions of Moodle.';
$string['registration_help'] = 'By registering:
* You will receive security alerts
* You can activate mobile app push notifications from your site
* You are contributing to our Moodle statistics of the worldwide community';
$string['slasharguments'] = 'Use slash arguments';
$string['slashargumentswarning'] = 'It is recommended that the use of slash arguments is enabled. In future it will be required. For more details, see the documentation <a href="https://docs.moodle.org/en/admin/environment/slasharguments">Using slash arguments</a>.';

View File

@ -134,6 +134,3 @@ filterbothactive,core_grades
filterbyname,core_grades
filterfirstactive,core_grades
filterlastactive,core_grades
configslasharguments,core_admin
slasharguments,core_admin
slashargumentswarning,core_admin

View File

@ -6,6 +6,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 2.9
*/
define("core/url",["jquery","core/config"],(function($,config){return{fileUrl:function(relativeScript,slashArg){var url=config.wwwroot+relativeScript;return"/"!=slashArg.charAt(0)&&(slashArg="/"+slashArg),url+=slashArg},relativeUrl:function(relativePath,params,includeSessKey){if(0===relativePath.indexOf("http:")||0===relativePath.indexOf("https:")||relativePath.indexOf("://")>=0)throw new Error("relativeUrl function does not accept absolute urls");"/"!=relativePath.charAt(0)&&(relativePath="/"+relativePath),"admin"!==config.admin&&(relativePath=relativePath.replace(/^\/admin\//,"/"+config.admin+"/")),params=params||{},includeSessKey&&(params.sesskey=config.sesskey);var queryString="";return Object.keys(params).length&&(queryString=$.map(params,(function(value,param){return param+"="+value})).join("&")),""!==queryString?config.wwwroot+relativePath+"?"+queryString:config.wwwroot+relativePath},imageUrl:function(imagename,component){return M.util.image_url(imagename,component)}}}));
define("core/url",["jquery","core/config"],(function($,config){return{fileUrl:function(relativeScript,slashArg){var url=config.wwwroot+relativeScript;return"/"!=slashArg.charAt(0)&&(slashArg="/"+slashArg),config.slasharguments?url+=slashArg:url+="?file="+encodeURIComponent(slashArg),url},relativeUrl:function(relativePath,params,includeSessKey){if(0===relativePath.indexOf("http:")||0===relativePath.indexOf("https:")||relativePath.indexOf("://")>=0)throw new Error("relativeUrl function does not accept absolute urls");"/"!=relativePath.charAt(0)&&(relativePath="/"+relativePath),"admin"!==config.admin&&(relativePath=relativePath.replace(/^\/admin\//,"/"+config.admin+"/")),params=params||{},includeSessKey&&(params.sesskey=config.sesskey);var queryString="";return Object.keys(params).length&&(queryString=$.map(params,(function(value,param){return param+"="+value})).join("&")),""!==queryString?config.wwwroot+relativePath+"?"+queryString:config.wwwroot+relativePath},imageUrl:function(imagename,component){return M.util.image_url(imagename,component)}}}));
//# sourceMappingURL=url.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -42,7 +42,11 @@ define(['jquery', 'core/config'], function($, config) {
if (slashArg.charAt(0) != '/') {
slashArg = '/' + slashArg;
}
url += slashArg;
if (config.slasharguments) {
url += slashArg;
} else {
url += '?file=' + encodeURIComponent(slashArg);
}
return url;
},

View File

@ -174,12 +174,15 @@ class page_requirements_manager {
public function __construct() {
global $CFG;
// You may need to set up URL rewrite rule because oversized URLs might not be allowed by web server.
$sep = empty($CFG->yuislasharguments) ? '?' : '/';
$this->yui3loader = new stdClass();
$this->YUI_config = new yui();
// Set up some loader options.
$this->yui3loader->local_base = $CFG->wwwroot . '/lib/yuilib/' . $CFG->yui3version . '/';
$this->yui3loader->local_comboBase = $CFG->wwwroot . '/theme/yui_combo.php/';
$this->yui3loader->local_comboBase = $CFG->wwwroot . '/theme/yui_combo.php' . $sep;
$this->yui3loader->base = $this->yui3loader->local_base;
$this->yui3loader->comboBase = $this->yui3loader->local_comboBase;
@ -208,7 +211,7 @@ class page_requirements_manager {
$this->YUI_config->add_group('yui2', [
// Loader configuration for our 2in3.
'base' => $CFG->wwwroot . '/lib/yuilib/2in3/' . $CFG->yui2version . '/build/',
'comboBase' => $CFG->wwwroot . '/theme/yui_combo.php/',
'comboBase' => $CFG->wwwroot . '/theme/yui_combo.php' . $sep,
'combine' => $this->yui3loader->combine,
'ext' => false,
'root' => '2in3/' . $CFG->yui2version . '/build/',
@ -222,9 +225,9 @@ class page_requirements_manager {
$configname = $this->YUI_config->set_config_source('lib/yui/config/moodle.js');
$this->YUI_config->add_group('moodle', [
'name' => 'moodle',
'base' => $CFG->wwwroot . '/theme/yui_combo.php/m/' . $jsrev . '/',
'base' => $CFG->wwwroot . '/theme/yui_combo.php' . $sep . 'm/' . $jsrev . '/',
'combine' => $this->yui3loader->combine,
'comboBase' => $CFG->wwwroot . '/theme/yui_combo.php/',
'comboBase' => $CFG->wwwroot . '/theme/yui_combo.php' . $sep,
'ext' => false,
'root' => 'm/' . $jsrev . '/', // Add the rev to the root path so that we can control caching.
'patterns' => [
@ -239,7 +242,7 @@ class page_requirements_manager {
'name' => 'gallery',
'base' => $CFG->wwwroot . '/lib/yuilib/gallery/',
'combine' => $this->yui3loader->combine,
'comboBase' => $CFG->wwwroot . '/theme/yui_combo.php/',
'comboBase' => $CFG->wwwroot . '/theme/yui_combo.php' . $sep,
'ext' => false,
'root' => 'gallery/' . $jsrev . '/',
'patterns' => [
@ -318,6 +321,7 @@ class page_requirements_manager {
'sessiontimeout' => $CFG->sessiontimeout,
'sessiontimeoutwarning' => $CFG->sessiontimeoutwarning,
'themerev' => theme_get_revision(),
'slasharguments' => (int)(!empty($CFG->slasharguments)),
'theme' => $page->theme->name,
'iconsystemmodule' => $iconsystem->get_amd_name(),
'jsrev' => $this->get_jsrev(),
@ -602,9 +606,23 @@ class page_requirements_manager {
debugging("Invalid file '$file' specified in jQuery plugin '$plugin' in component '$component'");
continue;
}
$url = new moodle_url("/theme/jquery.php");
$url->set_slashargument("/$component/$file");
if (!empty($CFG->slasharguments)) {
$url = new moodle_url("/theme/jquery.php");
$url->set_slashargument("/$component/$file");
} else {
// This is not really good, we need slasharguments for relative links, this means no caching...
$path = realpath("$componentdir/jquery/$file");
if (strpos($path, $CFG->dirroot) === 0) {
$url = $CFG->wwwroot . preg_replace('/^' . preg_quote($CFG->dirroot, '/') . '/', '', $path);
// Replace all occurences of backslashes characters in url to forward slashes.
$url = str_replace('\\', '/', $url);
$url = new moodle_url($url);
} else {
// Bad luck, fix your server!
debugging("Moodle jQuery integration requires 'slasharguments' setting to be enabled.");
continue;
}
}
$this->jqueryplugins[$plugin]->urls[] = $url;
}
@ -751,9 +769,13 @@ class page_requirements_manager {
}
if (substr($url, -3) === '.js') {
$jsrev = $this->get_jsrev();
$returnurl = new moodle_url('/lib/javascript.php');
$returnurl->set_slashargument('/' . $jsrev . $url);
return $returnurl;
if (empty($CFG->slasharguments)) {
return new moodle_url('/lib/javascript.php', ['rev' => $jsrev, 'jsfile' => $url]);
} else {
$returnurl = new moodle_url('/lib/javascript.php');
$returnurl->set_slashargument('/' . $jsrev . $url);
return $returnurl;
}
} else {
return new moodle_url($url);
}
@ -1447,8 +1469,11 @@ class page_requirements_manager {
$requirejsconfig = file_get_contents($CFG->dirroot . '/lib/requirejs/moodle-config.js');
// No extension required.
$jsextension = '';
// No extension required unless slash args is disabled.
$jsextension = '.js';
if (!empty($CFG->slasharguments)) {
$jsextension = '';
}
$minextension = '.min';
if (!$cachejs) {

View File

@ -682,7 +682,15 @@ class theme_config {
}
$url = new moodle_url("/theme/styles.php");
$url->set_slashargument("/{$this->name}/{$rev}/{$type}", 'noparam');
if (!empty($CFG->slasharguments)) {
$url->set_slashargument("/{$this->name}/{$rev}/{$type}", 'noparam', true);
} else {
$url->params([
'theme' => $this->name,
'rev' => $rev,
'type' => $type,
]);
}
} else {
$url = new moodle_url('/theme/styles_debug.php', [
'theme' => $this->name,
@ -817,17 +825,30 @@ class theme_config {
$rev .= "_{$themesubrevision}";
}
$slashargs = '';
if (!$svg) {
// We add a simple /_s to the start of the path.
// The underscore is used to ensure that it isn't a valid theme name.
$slashargs .= '/_s' . $slashargs;
if (!empty($CFG->slasharguments)) {
$slashargs = '';
if (!$svg) {
// We add a simple /_s to the start of the path.
// The underscore is used to ensure that it isn't a valid theme name.
$slashargs .= '/_s' . $slashargs;
}
$slashargs .= '/' . $this->name . '/' . $rev . '/' . $filename;
if ($separate) {
$slashargs .= '/chunk0';
}
$url->set_slashargument($slashargs, 'noparam', true);
} else {
$params = ['theme' => $this->name, 'rev' => $rev, 'type' => $filename];
if (!$svg) {
// We add an SVG param so that we know not to serve SVG images.
// We do this because all modern browsers support SVG and this param will one day be removed.
$params['svg'] = '0';
}
if ($separate) {
$params['chunk'] = '0';
}
$url->params($params);
}
$slashargs .= '/' . $this->name . '/' . $rev . '/' . $filename;
if ($separate) {
$slashargs .= '/chunk0';
}
$url->set_slashargument($slashargs, 'noparam');
$urls[] = $url;
} else {
$baseurl = new moodle_url('/theme/styles_debug.php');
@ -1436,9 +1457,9 @@ class theme_config {
return null;
}
if ($rev > 0) {
if (!empty($CFG->slasharguments) && $rev > 0) {
$url = new moodle_url("/theme/javascript.php");
$url->set_slashargument('/' . $this->name . '/' . $rev . '/' . $params['type'], 'noparam');
$url->set_slashargument('/' . $this->name . '/' . $rev . '/' . $params['type'], 'noparam', true);
return $url;
} else {
return new moodle_url('/theme/javascript.php', $params);
@ -1676,14 +1697,14 @@ class theme_config {
$params['image'] = $imagename;
$url = new moodle_url("/theme/image.php");
if ($rev > 0) {
if (!empty($CFG->slasharguments) && $rev > 0) {
$path = '/' . $params['theme'] . '/' . $params['component'] . '/' . $params['rev'] . '/' . $params['image'];
if (!$svg) {
// We add a simple /_s to the start of the path.
// The underscore is used to ensure that it isn't a valid theme name.
$path = '/_s' . $path;
}
$url->set_slashargument($path, 'noparam');
$url->set_slashargument($path, 'noparam', true);
} else {
if (!$svg) {
// We add an SVG param so that we know not to serve SVG images.
@ -1722,9 +1743,9 @@ class theme_config {
$params['font'] = $font;
$url = new moodle_url("/theme/font.php");
if ($rev > 0) {
if (!empty($CFG->slasharguments) && $rev > 0) {
$path = '/' . $params['theme'] . '/' . $params['component'] . '/' . $params['rev'] . '/' . $params['font'];
$url->set_slashargument($path, 'noparam');
$url->set_slashargument($path, 'noparam', true);
} else {
$url->params($params);
}

View File

@ -580,21 +580,24 @@ class url {
*
* @param string $path usually file path
* @param string $parameter name of page parameter if slasharguments not supported
* @param bool|null $supported This parameter has been deprecated since 4.5 and should not be used anymore.
* @todo Final deprecation on Moodle 6.0. See MDL-82768.
* @param bool $supported usually null, then it depends on $CFG->slasharguments, use true or false for other servers
*/
public function set_slashargument($path, $parameter = 'file', ?bool $supported = null) {
if ($supported !== null) {
debugging(
'Deprecated argument passed to ' . __FUNCTION__,
DEBUG_DEVELOPER,
);
public function set_slashargument($path, $parameter = 'file', $supported = null) {
global $CFG;
if (is_null($supported)) {
$supported = !empty($CFG->slasharguments);
}
if ($supported) {
$parts = explode('/', $path);
$parts = array_map('rawurlencode', $parts);
$path = implode('/', $parts);
$this->slashargument = $path;
unset($this->params[$parameter]);
} else {
$this->slashargument = '';
$this->params[$parameter] = $path;
}
$parts = explode('/', $path);
$parts = array_map('rawurlencode', $parts);
$path = implode('/', $parts);
$this->slashargument = $path;
unset($this->params[$parameter]);
}
// Static factory methods.
@ -697,7 +700,9 @@ class url {
$urlbase = "$CFG->wwwroot/tokenpluginfile.php";
$userid = $includetoken === true ? $USER->id : $includetoken;
$token = get_user_key('core_files', $userid);
$path[] = $token;
if ($CFG->slasharguments) {
$path[] = $token;
}
} else {
$urlbase = "$CFG->wwwroot/pluginfile.php";
}
@ -711,7 +716,10 @@ class url {
$path = "/" . implode('/', $path) . "{$pathname}{$filename}";
$url = self::make_file_url($urlbase, $path, $forcedownload);
$url = self::make_file_url($urlbase, $path, $forcedownload, $includetoken);
if ($includetoken && empty($CFG->slasharguments)) {
$url->param('token', $token);
}
return $url;
}
@ -823,20 +831,16 @@ class url {
*
* By default the path includes slash-arguments (for example,
* '/myfile.php/extra/arguments') so it is what you would expect from a
* URL path.
* URL path. If you don't want this behaviour, you can opt to exclude the
* slash arguments. (Be careful: if the $CFG variable slasharguments is
* disabled, these URLs will have a different format and you may need to
* look at the 'file' parameter too.)
*
* @param bool|null $includeslashargument This parameter has been deprecated since 4.5 and should not be used anymore.
* Final deprecation on Moodle 6.0. See MDL-82768.
* @param bool $includeslashargument If true, includes slash arguments
* @return string Path of URL
*/
public function get_path(?bool $includeslashargument = null) {
if ($includeslashargument !== null) {
debugging(
'The includeslashargument argument has been deprecated. Please remove it from your method calls.',
DEBUG_DEVELOPER,
);
}
return $this->path . $this->slashargument;
public function get_path($includeslashargument = true) {
return $this->path . ($includeslashargument ? $this->slashargument : '');
}
/**

View File

@ -1445,5 +1445,13 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2024092600.00);
}
if ($oldversion < 2024100100.01) {
// Set the slasharguments to 1 as default.
set_config('slasharguments', 1);
// Main savepoint reached.
upgrade_main_savepoint(true, 2024100100.01);
}
return true;
}

View File

@ -785,30 +785,3 @@ function plagiarism_get_file_results(): void {
function plagiarism_update_status(): void {
\core\deprecation::emit_deprecation_if_present(__FUNCTION__);
}
/**
* Method used to check the usage of slasharguments config and display a warning message.
*
* @param environment_results $result object to update, if relevant.
* @return environment_results|null updated results or null if slasharguments is disabled.
*
* @deprecated Since Moodle 4.5
* @todo Final deprecation on Moodle 6.0. See MDL-82768.
*/
#[\core\attribute\deprecated(
since: '4.5',
mdl: 'MDL-62640',
reason: 'Removed the option to disable slash arguments (slashargs)',
)]
function check_slasharguments(environment_results $result) {
\core\deprecation::emit_deprecation_if_present(__FUNCTION__);
global $CFG;
if (!during_initial_install() && empty($CFG->slasharguments)) {
$result->setInfo('slasharguments');
$result->setStatus(false);
return $result;
}
return null;
}

View File

@ -73,12 +73,20 @@ function file_encode_url($urlbase, $path, $forcedownload=false, $https=false) {
//TODO: deprecate this
$parts = explode('/', $path);
$parts = array_map('rawurlencode', $parts);
$path = implode('/', $parts);
$return = $urlbase . $path;
if ($forcedownload) {
$return .= '?forcedownload=1';
if ($CFG->slasharguments) {
$parts = explode('/', $path);
$parts = array_map('rawurlencode', $parts);
$path = implode('/', $parts);
$return = $urlbase.$path;
if ($forcedownload) {
$return .= '?forcedownload=1';
}
} else {
$path = rawurlencode($path);
$return = $urlbase.'?file='.$path;
if ($forcedownload) {
$return .= '&amp;forcedownload=1';
}
}
if ($https) {
@ -496,7 +504,13 @@ function file_rewrite_pluginfile_urls($text, $file, $contextid, $component, $fil
$finalfile = basename($file);
$tokenfile = "token{$finalfile}";
$file = substr($file, 0, strlen($file) - strlen($finalfile)) . $tokenfile;
$baseurl = "{$CFG->wwwroot}/{$file}/{$token}";
$baseurl = "{$CFG->wwwroot}/{$file}";
if (!$CFG->slasharguments) {
$baseurl .= "?token={$token}&file=";
} else {
$baseurl .= "/{$token}";
}
}
$baseurl .= "/{$contextid}/{$component}/{$filearea}/";

View File

@ -42,10 +42,17 @@ M.util.image_url = function(imagename, component) {
}
var url = M.cfg.wwwroot + '/theme/image.php';
if (!M.cfg.svgicons) {
url += '/_s';
if (M.cfg.themerev > 0 && M.cfg.slasharguments == 1) {
if (!M.cfg.svgicons) {
url += '/_s';
}
url += '/' + M.cfg.theme + '/' + component + '/' + M.cfg.themerev + '/' + imagename;
} else {
url += '?theme=' + M.cfg.theme + '&component=' + component + '&rev=' + M.cfg.themerev + '&image=' + imagename;
if (!M.cfg.svgicons) {
url += '&svg=0';
}
}
url += '/' + M.cfg.theme + '/' + component + '/' + M.cfg.themerev + '/' + imagename;
return url;
};

View File

@ -1317,7 +1317,9 @@ EOF;
* Test file_rewrite_pluginfile_urls with includetoken.
*/
public function test_file_rewrite_pluginfile_urls_includetoken(): void {
global $USER;
global $USER, $CFG;
$CFG->slasharguments = true;
$this->resetAfterTest();
@ -1360,6 +1362,43 @@ EOF;
$this->assertEquals($expectedtext, $finaltext);
}
/**
* Test file_rewrite_pluginfile_urls with includetoken with slasharguments disabled..
*/
public function test_file_rewrite_pluginfile_urls_includetoken_no_slashargs(): void {
global $USER, $CFG;
$CFG->slasharguments = false;
$this->resetAfterTest();
$syscontext = \context_system::instance();
$originaltext = 'Fake test with an image <img src="@@PLUGINFILE@@/image.png">';
$options = ['includetoken' => true];
// Rewrite the content. This will generate a new token.
$finaltext = file_rewrite_pluginfile_urls(
$originaltext, 'pluginfile.php', $syscontext->id, 'user', 'private', 0, $options);
$token = get_user_key('core_files', $USER->id);
$expectedurl = new \moodle_url("/tokenpluginfile.php");
$expectedurl .= "?token={$token}&file=/{$syscontext->id}/user/private/0/image.png";
$expectedtext = "Fake test with an image <img src=\"{$expectedurl}\">";
$this->assertEquals($expectedtext, $finaltext);
// Do it again - the second time will use an existing token.
$finaltext = file_rewrite_pluginfile_urls(
$originaltext, 'pluginfile.php', $syscontext->id, 'user', 'private', 0, $options);
$this->assertEquals($expectedtext, $finaltext);
// Now undo.
$options['reverse'] = true;
$finaltext = file_rewrite_pluginfile_urls($finaltext, 'pluginfile.php', $syscontext->id, 'user', 'private', 0, $options);
// Compare the final text is the same that the original.
$this->assertEquals($originaltext, $finaltext);
}
/**
* Helpter function to create draft files
*
@ -2005,36 +2044,6 @@ EOF;
],
];
}
/**
* Tests the file_encode_url function to ensure it generates the correct URLs.
*
* @dataProvider file_encode_url_provider
* @covers ::file_encode_url()
*
* @param string $urlbase The base URL to be used in the encoding.
* @param string $path The path to be appended to the base URL.
* @param bool $forcedownload Whether to force the file to download.
* @param bool $https Whether to use HTTPS for the URL.
* @param string $expected The expected URL after encoding.
* @return void
*/
public function test_file_encode_url(string $urlbase, string $path, bool $forcedownload, bool $https, string $expected): void {
$actual = file_encode_url($urlbase, $path, $forcedownload, $https);
$this->assertSame($expected, $actual);
}
/**
* Provides data sets for test_file_encode_url.
*/
public static function file_encode_url_provider(): array {
return [
['http://local.test/', '1/1', false, false, 'http://local.test/1/1'],
['http://local.test/', '1/number two', true, false, 'http://local.test/1/number%20two?forcedownload=1'],
['http://local.test/', 'number@one/3', true, true, 'https://local.test/number%40one/3?forcedownload=1'],
];
}
}
/**

View File

@ -136,6 +136,7 @@ final class outputcomponents_test extends \advanced_testcase {
// Verify new install contains expected defaults.
$this->assertSame(theme_config::DEFAULT_THEME, $CFG->theme);
$this->assertEquals(1, $CFG->slasharguments);
$this->assertEquals(1, $CFG->themerev);
$this->assertEquals(0, $CFG->themedesignermode);
$this->assertSame('https://www.example.com/moodle', $CFG->wwwroot);
@ -304,13 +305,14 @@ final class outputcomponents_test extends \advanced_testcase {
// Test non-slashargument images.
set_config('theme', 'classic');
$CFG->wwwroot = str_replace('https:', 'http:', $CFG->wwwroot);
$CFG->slasharguments = 0;
$page = new \moodle_page();
$page->set_url('/user/profile.php');
$page->set_context(\context_system::instance());
$renderer = $page->get_renderer('core');
$up3 = new user_picture($user3);
$this->assertSame($CFG->wwwroot.'/theme/image.php/classic/core/1/u/f2', $up3->get_url($page, $renderer)->out(false));
$this->assertSame($CFG->wwwroot.'/theme/image.php?theme=classic&component=core&rev=1&image=u%2Ff2', $up3->get_url($page, $renderer)->out(false));
}
public function test_empty_menu(): void {

View File

@ -61,13 +61,16 @@ final class outputrequirementslib_test extends \advanced_testcase {
/**
* Test for the jquery_plugin method.
*
* Test to make sure that backslashes are not generated.
* Test to make sure that backslashes are not generated with either slasharguments set to on or off.
*/
public function test_jquery_plugin(): void {
global $PAGE;
global $CFG, $PAGE;
$this->resetAfterTest();
// With slasharguments on.
$CFG->slasharguments = 1;
$page = new \moodle_page();
$requirements = $page->requires;
// Assert successful method call.
@ -79,6 +82,20 @@ final class outputrequirementslib_test extends \advanced_testcase {
$requirecode = $requirements->get_top_of_body_code($renderer);
// Make sure that the generated code does not contain backslashes.
$this->assertFalse(strpos($requirecode, '\\'), "Output contains backslashes: " . $requirecode);
// With slasharguments off.
$CFG->slasharguments = 0;
$page = new \moodle_page();
$requirements = $page->requires;
// Assert successful method call.
$this->assertTrue($requirements->jquery_plugin('jquery'));
$this->assertTrue($requirements->jquery_plugin('ui'));
// Get the code containing the required jquery plugins.
$requirecode = $requirements->get_top_of_body_code($renderer);
// Make sure that the generated code does not contain backslashes.
$this->assertFalse(strpos($requirecode, '\\'), "Output contains backslashes: " . $requirecode);
}
/**
@ -117,6 +134,7 @@ final class outputrequirementslib_test extends \advanced_testcase {
* Test the actual URL through which a JavaScript file is served.
*
* @param \moodle_url $moodleurl The <u>moodle_url</u> instance pointing to a web resource.
* @param int $cfgslashargs The value to force $CFG->slasharguments.
* @param string $expected The expected output URL.
* @throws ReflectionException if the class does not exist.
* @see \page_requirements_manager::js_fix_url()
@ -124,12 +142,18 @@ final class outputrequirementslib_test extends \advanced_testcase {
* @covers \page_requirements_manager::js_fix_url
* @dataProvider js_fix_url_moodle_url_provider
*/
public function test_js_fix_url_moodle_url(\moodle_url $moodleurl, string $expected): void {
public function test_js_fix_url_moodle_url(\moodle_url $moodleurl, int $cfgslashargs, string $expected): void {
global $CFG;
$defaultslashargs = $CFG->slasharguments;
$CFG->slasharguments = $cfgslashargs;
$rc = new \ReflectionClass(\page_requirements_manager::class);
$rcm = $rc->getMethod('js_fix_url');
$requires = new \page_requirements_manager();
$actualmoodleurl = $rcm->invokeArgs($requires, [$moodleurl]);
$this->assertEquals($expected, $actualmoodleurl->out(false));
$CFG->slasharguments = $defaultslashargs;
}
/**
@ -145,30 +169,47 @@ final class outputrequirementslib_test extends \advanced_testcase {
$libdir = rtrim($CFG->libdir, '/');
$admin = "/{$CFG->admin}/"; // Deprecated, just for coverage purposes.
// Note: $CFG->slasharguments is enabled by default; it will be a forced setting one day (MDL-62640).
return [
'Environment XML file' => [
new \moodle_url('/admin/environment.xml'),
$wwwroot . $admin . 'environment.xml',
0,
$wwwroot . $admin . 'environment.xml'
],
'Google Maps CDN (HTTPS)' => [
new \moodle_url('https://maps.googleapis.com/maps/api/js', ['key' => 'googlemapkey3', 'sensor' => 'false']),
'https://maps.googleapis.com/maps/api/js?key=googlemapkey3&sensor=false',
1,
'https://maps.googleapis.com/maps/api/js?key=googlemapkey3&sensor=false'
],
'Google Maps CDN (HTTP)' => [
new \moodle_url('http://maps.googleapis.com/maps/api/js', ['key' => 'googlemapkey3', 'sensor' => 'false']),
'http://maps.googleapis.com/maps/api/js?key=googlemapkey3&sensor=false',
0,
'http://maps.googleapis.com/maps/api/js?key=googlemapkey3&sensor=false'
],
'H5P JS internal resource' => [
'H5P JS internal resource (slasharguments on)' => [
new \moodle_url('/h5p/js/embed.js'),
$wwwroot . '/lib/javascript.php/1/h5p/js/embed.js',
1,
$wwwroot . '/lib/javascript.php/1/h5p/js/embed.js'
],
'H5P JS internal resource (slasharguments off)' => [
new \moodle_url('/h5p/js/embed.js'),
0,
$wwwroot . '/lib/javascript.php?rev=1&jsfile=%2Fh5p%2Fjs%2Fembed.js'
],
'A custom Moodle CSS Handler' => [
new \moodle_url('/mod/data/css.php?d=1234567890'),
$wwwroot . '/mod/data/css.php?d=1234567890',
1,
$wwwroot . '/mod/data/css.php?d=1234567890'
],
'A custom Moodle JS Handler' => [
'A custom Moodle JS Handler (slasharguments on)' => [
new \moodle_url('/mod/data/js.php?d=1234567890'),
$wwwroot . '/mod/data/js.php?d=1234567890',
1,
$wwwroot . '/mod/data/js.php?d=1234567890'
],
'A custom Moodle JS Handler (slasharguments off)' => [
new \moodle_url('/mod/data/js.php?d=1234567890'),
0,
$wwwroot . '/mod/data/js.php?d=1234567890'
],
];
}
@ -177,18 +218,25 @@ final class outputrequirementslib_test extends \advanced_testcase {
* Test the actual url through which a JavaScript file is served.
*
* @param string $url The URL pointing to a web resource.
* @param int $cfgslashargs The value to force $CFG->slasharguments.
* @param string $expected The expected output URL.
* @throws ReflectionException if the class does not exist.
* @see \page_requirements_manager::js_fix_url()
* @covers \page_requirements_manager::js_fix_url
* @dataProvider js_fix_url_plain_string_provider
*/
public function test_js_fix_url_plain_string(string $url, string $expected): void {
public function test_js_fix_url_plain_string(string $url, int $cfgslashargs, string $expected): void {
global $CFG;
$defaultslashargs = $CFG->slasharguments;
$CFG->slasharguments = $cfgslashargs;
$rc = new \ReflectionClass(\page_requirements_manager::class);
$rcm = $rc->getMethod('js_fix_url');
$requires = new \page_requirements_manager();
$actualmoodleurl = $rcm->invokeArgs($requires, [$url]);
$this->assertEquals($expected, $actualmoodleurl->out(false));
$CFG->slasharguments = $defaultslashargs;
}
/**
@ -202,34 +250,47 @@ final class outputrequirementslib_test extends \advanced_testcase {
$wwwroot = rtrim($CFG->wwwroot, '/');
$admin = "/{$CFG->admin}/"; // Deprecated, just for coverage purposes.
// Note: $CFG->slasharguments is enabled by default; it will be a forced setting one day (MDL-62640).
return [
'Environment XML file' => [
'/admin/environment.xml',
$wwwroot . $admin . 'environment.xml',
0,
$wwwroot . $admin . 'environment.xml'
],
'Data JS' => [
'/mod/data/data.js',
$wwwroot . '/lib/javascript.php/1/mod/data/data.js',
1,
$wwwroot . '/lib/javascript.php/1/mod/data/data.js'
],
'SCORM Request JS' => [
'/mod/scorm/request.js',
$wwwroot . '/lib/javascript.php/1/mod/scorm/request.js',
1,
$wwwroot . '/lib/javascript.php/1/mod/scorm/request.js'
],
'Wiki Editors Buttons JS' => [
'/mod/wiki/editors/wiki/buttons.js',
$wwwroot . '/lib/javascript.php/1/mod/wiki/editors/wiki/buttons.js',
1,
$wwwroot . '/lib/javascript.php/1/mod/wiki/editors/wiki/buttons.js'
],
'A non-JS internal resource' => [
'/theme/boost/pix/favicon.ico',
$wwwroot . '/theme/boost/pix/favicon.ico',
0,
$wwwroot . '/theme/boost/pix/favicon.ico'
],
'A custom Moodle CSS Handler' => [
'/mod/data/css.php?d=1234567890',
$wwwroot . '/mod/data/css.php?d=1234567890',
1,
$wwwroot . '/mod/data/css.php?d=1234567890'
],
'A custom Moodle JS Handler' => [
'A custom Moodle JS Handler (slasharguments on)' => [
'/mod/data/js.php?d=1234567890',
$wwwroot . '/mod/data/js.php?d=1234567890',
1,
$wwwroot . '/mod/data/js.php?d=1234567890'
],
'A custom Moodle JS Handler (slasharguments off)' => [
'/mod/data/js.php?d=1234567890',
0,
$wwwroot . '/mod/data/js.php?d=1234567890'
],
];
}

View File

@ -68,6 +68,7 @@ final class url_test extends \advanced_testcase {
$url = new url('http://www.example.org/pluginfile.php/slash/arguments');
$this->assertSame('/pluginfile.php/slash/arguments', $url->get_path());
$this->assertSame('/pluginfile.php', $url->get_path(false));
}
public function test_round_trip(): void {
@ -303,12 +304,16 @@ final class url_test extends \advanced_testcase {
* Test the make_pluginfile_url function.
*
* @dataProvider make_pluginfile_url_provider
* @param bool $slashargs
* @param array $args Args to be provided to make_pluginfile_url
* @param string $expected The expected result
*/
public function test_make_pluginfile_url(array $args, string $expected): void {
public function test_make_pluginfile_url($slashargs, $args, $expected): void {
global $CFG;
$this->resetAfterTest();
$CFG->slasharguments = $slashargs;
$url = call_user_func_array([url::class, 'make_pluginfile_url'], $args);
$this->assertMatchesRegularExpression($expected, $url->out(true));
}
@ -323,6 +328,7 @@ final class url_test extends \advanced_testcase {
$tokenbaseurl = "https://www.example.com/moodle/tokenpluginfile.php";
return [
'Standard with slashargs' => [
'slashargs' => true,
'args' => [
1,
'mod_forum',
@ -333,7 +339,20 @@ final class url_test extends \advanced_testcase {
],
'expected' => "@{$baseurl}/1/mod_forum/posts/422/my/location/file.png@",
],
'Standard without slashargs' => [
'slashargs' => false,
'args' => [
1,
'mod_forum',
'posts',
422,
'/my/location/',
'file.png',
],
'expected' => "@{$baseurl}\?file=%2F1%2Fmod_forum%2Fposts%2F422%2Fmy%2Flocation%2Ffile.png@",
],
'Token included with slashargs' => [
'slashargs' => true,
'args' => [
1,
'mod_forum',
@ -346,6 +365,21 @@ final class url_test extends \advanced_testcase {
],
'expected' => "@{$tokenbaseurl}/[^/]*/1/mod_forum/posts/422/my/location/file.png@",
],
'Token included without slashargs' => [
'slashargs' => false,
'args' => [
1,
'mod_forum',
'posts',
422,
'/my/location/',
'file.png',
false,
true,
],
'expected' =>
"@{$tokenbaseurl}\?file=%2F1%2Fmod_forum%2Fposts%2F422%2Fmy%2Flocation%2Ffile.png&amp;token=[a-z0-9]*@",
],
];
}

View File

@ -824,90 +824,125 @@ EXPECTED;
* Data provider for test_get_file_argument.
*/
public static function provider_get_file_argument() {
return [
return array(
// Serving SCORM content w/o HTTP GET params.
[
[
array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/3854/mod_scorm/content/1/swf.html',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/3854/mod_scorm/content/1/swf.html',
],
'/3854/mod_scorm/content/1/swf.html',
],
), 0, '/3854/mod_scorm/content/1/swf.html'),
array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/3854/mod_scorm/content/1/swf.html',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/3854/mod_scorm/content/1/swf.html',
), 1, '/3854/mod_scorm/content/1/swf.html'),
// Serving SCORM content w/ HTTP GET 'file' as first param.
[
[
array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/3854/mod_scorm/content/1/swf.html?file=video_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/3854/mod_scorm/content/1/swf.html',
],
'/3854/mod_scorm/content/1/swf.html',
],
), 0, '/3854/mod_scorm/content/1/swf.html'),
array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/3854/mod_scorm/content/1/swf.html?file=video_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/3854/mod_scorm/content/1/swf.html',
), 1, '/3854/mod_scorm/content/1/swf.html'),
// Serving SCORM content w/ HTTP GET 'file' not as first param.
[
[
array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/3854/mod_scorm/content/1/swf.html?foo=bar&file=video_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/3854/mod_scorm/content/1/swf.html',
],
'/3854/mod_scorm/content/1/swf.html',
],
), 0, '/3854/mod_scorm/content/1/swf.html'),
array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/3854/mod_scorm/content/1/swf.html?foo=bar&file=video_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/3854/mod_scorm/content/1/swf.html',
), 1, '/3854/mod_scorm/content/1/swf.html'),
// Serving content from a generic activity w/ HTTP GET 'file', still forcing slash arguments.
[
[
array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/3854/whatever/content/1/swf.html?file=video_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/3854/whatever/content/1/swf.html',
],
'/3854/whatever/content/1/swf.html',
],
), 0, '/3854/whatever/content/1/swf.html'),
array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/3854/whatever/content/1/swf.html?file=video_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/3854/whatever/content/1/swf.html',
), 1, '/3854/whatever/content/1/swf.html'),
// Serving content from a generic activity w/ HTTP GET 'file', still forcing slash arguments (edge case).
[
[
array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/?file=video_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/',
],
'video_.swf',
],
), 0, 'video_.swf'),
array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php/?file=video_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
'PATH_INFO' => '/',
), 1, 'video_.swf'),
// Serving content from a generic activity w/ HTTP GET 'file', w/o forcing slash arguments.
[
[
array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php?file=%2F3854%2Fwhatever%2Fcontent%2F1%2Fswf.html%3Ffile%3Dvideo_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
],
'/3854/whatever/content/1/swf.html?file=video_.swf',
],
];
), 0, '/3854/whatever/content/1/swf.html?file=video_.swf'),
array(array(
'SERVER_SOFTWARE' => 'Apache',
'SERVER_PORT' => '80',
'REQUEST_METHOD' => 'GET',
'REQUEST_URI' => '/pluginfile.php?file=%2F3854%2Fwhatever%2Fcontent%2F1%2Fswf.html%3Ffile%3Dvideo_.swf',
'SCRIPT_NAME' => '/pluginfile.php',
), 1, '/3854/whatever/content/1/swf.html?file=video_.swf'),
);
}
/**
* Tests for get_file_argument() function.
*
* @param array $server mockup for $_SERVER.
* @param string $expected Expected value.
* @param string $cfgslasharguments slasharguments setting.
* @param string|false $expected Expected value.
* @dataProvider provider_get_file_argument
* @covers ::get_file_argument
*/
public function test_get_file_argument(array $server, string $expected): void {
public function test_get_file_argument($server, $cfgslasharguments, $expected): void {
global $CFG;
// Overwrite the related settings.
$currentsetting = $CFG->slasharguments;
$CFG->slasharguments = $cfgslasharguments;
// Mock global $_SERVER.
$currentserver = isset($_SERVER) ? $_SERVER : null;
$_SERVER = $server;
@ -930,6 +965,7 @@ EXPECTED;
$this->assertEquals($expected, get_file_argument());
// Restore the current settings and global values.
$CFG->slasharguments = $currentsetting;
if (is_null($currentserver)) {
unset($_SERVER);
} else {

View File

@ -2278,6 +2278,24 @@ function check_database_storage_engine(environment_results $result) {
return null;
}
/**
* Method used to check the usage of slasharguments config and display a warning message.
*
* @param environment_results $result object to update, if relevant.
* @return environment_results|null updated results or null if slasharguments is disabled.
*/
function check_slasharguments(environment_results $result){
global $CFG;
if (!during_initial_install() && empty($CFG->slasharguments)) {
$result->setInfo('slasharguments');
$result->setStatus(false);
return $result;
}
return null;
}
/**
* This function verifies if the database has tables using innoDB Antelope row format.
*

View File

@ -1,2 +1 @@
completionscorerequired_help,mod_scorm
slashargs,mod_scorm

View File

@ -406,6 +406,7 @@ $string['sided'] = 'To the side';
$string['skipview'] = 'Student skip content structure page';
$string['skipview_help'] = 'This setting specifies whether the content structure page should ever be skipped (not displayed). If the package contains only one learning object, the content structure page can always be skipped.';
$string['skipviewdesc'] = 'This preference sets the default for when to skip content structure for a page';
$string['slashargs'] = 'WARNING: slash arguments is disabled on this site and objects may not function as expected!';
$string['stagesize'] = 'Stage size';
$string['stagesize_help'] = 'These two settings specify the frame/window width and height for the learning objects.';
$string['started'] = 'Started on';
@ -457,6 +458,3 @@ $string['youmustselectastatus'] = 'You must select a status to require';
// Deprecated since Moodle 4.3.
$string['completionscorerequired_help'] = 'Enabling this setting will require a user to have at least the minimum score entered to be marked complete in this SCORM activity, as well as any other Activity Completion requirements.';
// Deprecated since Moodle 4.5.
$string['slashargs'] = 'WARNING: slash arguments is disabled on this site and objects may not function as expected!';

View File

@ -29,6 +29,10 @@ class mod_scorm_mod_form extends moodleform_mod {
$mform = $this->_form;
if (!$CFG->slasharguments) {
$mform->addElement('static', '', '', $OUTPUT->notification(get_string('slashargs', 'scorm'), 'notifyproblem'));
}
$mform->addElement('header', 'general', get_string('general', 'form'));
// Name.

View File

@ -736,6 +736,9 @@ function wiki_parser_real_path($url, $context, $component, $filearea, $swid) {
} else {
$file = 'pluginfile.php';
if (!$CFG->slasharguments) {
$file = $file . '?file=';
}
$baseurl = "$CFG->wwwroot/$file/{$context->id}/$component/$filearea/$swid/";
// it is a file in current file area
return $baseurl . $url;

View File

@ -922,26 +922,4 @@ class lib_test extends \advanced_testcase {
return \calendar_event::create($event);
}
/**
* Tests the wiki_parser_real_path function to ensure it correctly resolves URLs.
*
* @covers ::wiki_parser_real_path()
*/
public function test_wiki_parser_real_path(): void {
global $CFG;
$this->resetAfterTest();
// Create the activity.
$course = $this->getDataGenerator()->create_course(['enablecompletion' => 1]);
$wiki = $this->getDataGenerator()->create_module('wiki', ['course' => $course->id]);
$context = \context_module::instance($wiki->cmid);
$moodleurl = new \moodle_url('/mod/wiki/view.php', ['id' => 2]);
$url = wiki_parser_real_path($moodleurl->out(), $context, 'mod_wiki', 'attachments', 3);
$this->assertSame("{$CFG->wwwroot}/mod/wiki/view.php?id=2", $url);
$url = wiki_parser_real_path('mod/wiki/view.php?id=2', $context, 'mod_wiki', 'attachments', 3);
$this->assertSame("{$CFG->wwwroot}/pluginfile.php/{$context->id}/mod_wiki/attachments/3/mod/wiki/view.php?id=2", $url);
}
}

View File

@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2024100100.00; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2024100100.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.
$release = '4.5rc1 (Build: 20241001)'; // Human-friendly version name