mirror of
https://github.com/moodle/moodle.git
synced 2025-08-08 18:36:42 +02:00
Merge branch 'w38_MDL-29401_m22_frankenstyle' of git://github.com/skodak/moodle
This commit is contained in:
commit
e135797586
50 changed files with 267 additions and 142 deletions
|
@ -3506,9 +3506,9 @@ class admin_setting_emoticons extends admin_setting {
|
|||
$emoticon = new stdClass();
|
||||
$emoticon->text = clean_param(trim($form['text'.$i]), PARAM_NOTAGS);
|
||||
$emoticon->imagename = clean_param(trim($form['imagename'.$i]), PARAM_PATH);
|
||||
$emoticon->imagecomponent = clean_param(trim($form['imagecomponent'.$i]), PARAM_SAFEDIR);
|
||||
$emoticon->imagecomponent = clean_param(trim($form['imagecomponent'.$i]), PARAM_COMPONENT);
|
||||
$emoticon->altidentifier = clean_param(trim($form['altidentifier'.$i]), PARAM_STRINGID);
|
||||
$emoticon->altcomponent = clean_param(trim($form['altcomponent'.$i]), PARAM_SAFEDIR);
|
||||
$emoticon->altcomponent = clean_param(trim($form['altcomponent'.$i]), PARAM_COMPONENT);
|
||||
|
||||
if (strpos($emoticon->text, ':/') !== false or strpos($emoticon->text, '//') !== false) {
|
||||
// prevent from breaking http://url.addresses by accident
|
||||
|
|
|
@ -1078,7 +1078,7 @@ class block_manager {
|
|||
* @return boolean true if anything was done. False if not.
|
||||
*/
|
||||
public function process_url_add() {
|
||||
$blocktype = optional_param('bui_addblock', null, PARAM_SAFEDIR);
|
||||
$blocktype = optional_param('bui_addblock', null, PARAM_PLUGIN);
|
||||
if (!$blocktype) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -117,8 +117,10 @@ function enrol_get_plugins($enabled) {
|
|||
function enrol_get_plugin($name) {
|
||||
global $CFG;
|
||||
|
||||
if ($name !== clean_param($name, PARAM_SAFEDIR)) {
|
||||
// ignore malformed plugin names completely
|
||||
$name = clean_param($name, PARAM_PLUGIN);
|
||||
|
||||
if (empty($name)) {
|
||||
// ignore malformed or missing plugin names completely
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -519,11 +519,13 @@ class file_storage {
|
|||
throw new file_exception('storedfileproblem', 'Invalid contextid');
|
||||
}
|
||||
|
||||
if ($component === '' or $component !== clean_param($component, PARAM_ALPHAEXT)) {
|
||||
$component = clean_param($component, PARAM_COMPONENT);
|
||||
if (empty($component)) {
|
||||
throw new file_exception('storedfileproblem', 'Invalid component');
|
||||
}
|
||||
|
||||
if ($filearea === '' or $filearea !== clean_param($filearea, PARAM_ALPHAEXT)) {
|
||||
$filearea = clean_param($filearea, PARAM_AREA);
|
||||
if (empty($filearea)) {
|
||||
throw new file_exception('storedfileproblem', 'Invalid filearea');
|
||||
}
|
||||
|
||||
|
@ -620,13 +622,15 @@ class file_storage {
|
|||
}
|
||||
|
||||
if ($key == 'component') {
|
||||
if ($value === '' or $value !== clean_param($value, PARAM_ALPHAEXT)) {
|
||||
$value = clean_param($value, PARAM_COMPONENT);
|
||||
if (empty($value)) {
|
||||
throw new file_exception('storedfileproblem', 'Invalid component');
|
||||
}
|
||||
}
|
||||
|
||||
if ($key == 'filearea') {
|
||||
if ($value === '' or $value !== clean_param($value, PARAM_ALPHAEXT)) {
|
||||
$value = clean_param($value, PARAM_AREA);
|
||||
if (empty($value)) {
|
||||
throw new file_exception('storedfileproblem', 'Invalid filearea');
|
||||
}
|
||||
}
|
||||
|
@ -755,11 +759,13 @@ class file_storage {
|
|||
throw new file_exception('storedfileproblem', 'Invalid contextid');
|
||||
}
|
||||
|
||||
if ($file_record->component === '' or $file_record->component !== clean_param($file_record->component, PARAM_ALPHAEXT)) {
|
||||
$file_record->component = clean_param($file_record->component, PARAM_COMPONENT);
|
||||
if (empty($file_record->component)) {
|
||||
throw new file_exception('storedfileproblem', 'Invalid component');
|
||||
}
|
||||
|
||||
if ($file_record->filearea === '' or $file_record->filearea !== clean_param($file_record->filearea, PARAM_ALPHAEXT)) {
|
||||
$file_record->filearea = clean_param($file_record->filearea, PARAM_AREA);
|
||||
if (empty($file_record->filearea)) {
|
||||
throw new file_exception('storedfileproblem', 'Invalid filearea');
|
||||
}
|
||||
|
||||
|
@ -848,11 +854,13 @@ class file_storage {
|
|||
throw new file_exception('storedfileproblem', 'Invalid contextid');
|
||||
}
|
||||
|
||||
if ($file_record->component === '' or $file_record->component !== clean_param($file_record->component, PARAM_ALPHAEXT)) {
|
||||
$file_record->component = clean_param($file_record->component, PARAM_COMPONENT);
|
||||
if (empty($file_record->component)) {
|
||||
throw new file_exception('storedfileproblem', 'Invalid component');
|
||||
}
|
||||
|
||||
if ($file_record->filearea === '' or $file_record->filearea !== clean_param($file_record->filearea, PARAM_ALPHAEXT)) {
|
||||
$file_record->filearea = clean_param($file_record->filearea, PARAM_AREA);
|
||||
if (empty($file_record->filearea)) {
|
||||
throw new file_exception('storedfileproblem', 'Invalid filearea');
|
||||
}
|
||||
|
||||
|
|
|
@ -284,6 +284,29 @@ define('PARAM_TIMEZONE', 'timezone');
|
|||
*/
|
||||
define('PARAM_CLEANFILE', 'file');
|
||||
|
||||
/**
|
||||
* PARAM_COMPONENT is used for full component names (aka frankenstyle) such as 'mod_forum', 'core_rating', 'auth_ldap'.
|
||||
* Short legacy subsystem names and module names are accepted too ex: 'forum', 'rating', 'user'.
|
||||
* Only lowercase ascii letters, numbers and underscores are allowed, it has to start with a letter.
|
||||
* NOTE: numbers and underscores are strongly discouraged in plugin names!
|
||||
*/
|
||||
define('PARAM_COMPONENT', 'component');
|
||||
|
||||
/**
|
||||
* PARAM_AREA is a name of area used when addressing files, comments, ratings, etc.
|
||||
* It is usually used together with context id and component.
|
||||
* Only lowercase ascii letters, numbers and underscores are allowed, it has to start with a letter.
|
||||
*/
|
||||
define('PARAM_AREA', 'area');
|
||||
|
||||
/**
|
||||
* PARAM_PLUGIN is used for plugin names such as 'forum', 'glossary', 'ldap', 'radius', 'paypal', 'completionstatus'.
|
||||
* Only lowercase ascii letters, numbers and underscores are allowed, it has to start with a letter.
|
||||
* NOTE: numbers and underscores are strongly discouraged in plugin names! Underscores are forbidden in module names.
|
||||
*/
|
||||
define('PARAM_PLUGIN', 'plugin');
|
||||
|
||||
|
||||
/// Web Services ///
|
||||
|
||||
/**
|
||||
|
@ -821,6 +844,34 @@ function clean_param($param, $type) {
|
|||
// easy, just strip all tags, if we ever want to fix orphaned '&' we have to do that in format_string()
|
||||
return strip_tags($param);
|
||||
|
||||
case PARAM_COMPONENT:
|
||||
// we do not want any guessing here, either the name is correct or not
|
||||
// please note only normalised component names are accepted
|
||||
if (!preg_match('/^[a-z]+(_[a-z][a-z0-9_]*)?[a-z0-9]$/', $param)) {
|
||||
return '';
|
||||
}
|
||||
if (strpos($param, '__') !== false) {
|
||||
return '';
|
||||
}
|
||||
if (strpos($param, 'mod_') === 0) {
|
||||
// module names must not contain underscores because we need to differentiate them from invalid plugin types
|
||||
if (substr_count($param, '_') != 1) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
return $param;
|
||||
|
||||
case PARAM_PLUGIN:
|
||||
case PARAM_AREA:
|
||||
// we do not want any guessing here, either the name is correct or not
|
||||
if (!preg_match('/^[a-z][a-z0-9_]*[a-z0-9]$/', $param)) {
|
||||
return '';
|
||||
}
|
||||
if (strpos($param, '__') !== false) {
|
||||
return '';
|
||||
}
|
||||
return $param;
|
||||
|
||||
case PARAM_SAFEDIR: // Remove everything not a-zA-Z0-9_-
|
||||
return preg_replace('/[^a-zA-Z0-9_-]/i', '', $param);
|
||||
|
||||
|
@ -988,8 +1039,10 @@ function clean_param($param, $type) {
|
|||
}
|
||||
|
||||
case PARAM_AUTH:
|
||||
$param = clean_param($param, PARAM_SAFEDIR);
|
||||
if (exists_auth_plugin($param)) {
|
||||
$param = clean_param($param, PARAM_PLUGIN);
|
||||
if (empty($param)) {
|
||||
return '';
|
||||
} else if (exists_auth_plugin($param)) {
|
||||
return $param;
|
||||
} else {
|
||||
return '';
|
||||
|
@ -1004,8 +1057,10 @@ function clean_param($param, $type) {
|
|||
}
|
||||
|
||||
case PARAM_THEME:
|
||||
$param = clean_param($param, PARAM_SAFEDIR);
|
||||
if (file_exists("$CFG->dirroot/theme/$param/config.php")) {
|
||||
$param = clean_param($param, PARAM_PLUGIN);
|
||||
if (empty($param)) {
|
||||
return '';
|
||||
} else if (file_exists("$CFG->dirroot/theme/$param/config.php")) {
|
||||
return $param;
|
||||
} else if (!empty($CFG->themedir) and file_exists("$CFG->themedir/$param/config.php")) {
|
||||
return $param;
|
||||
|
@ -7381,7 +7436,8 @@ function get_plugin_list($plugintype) {
|
|||
if (in_array($pluginname, $ignored)) {
|
||||
continue;
|
||||
}
|
||||
if ($pluginname !== clean_param($pluginname, PARAM_SAFEDIR)) {
|
||||
$pluginname = clean_param($pluginname, PARAM_PLUGIN);
|
||||
if (empty($pluginname)) {
|
||||
// better ignore plugins with problematic names here
|
||||
continue;
|
||||
}
|
||||
|
@ -7489,23 +7545,30 @@ function get_list_of_plugins($directory='mod', $exclude='', $basedir='') {
|
|||
*
|
||||
* @param string $type Plugin type e.g. 'mod'
|
||||
* @param string $name Plugin name
|
||||
* @param string $feature Feature code (FEATURE_xx constant)
|
||||
* @param string $feature Feature name
|
||||
* @param string $action Feature's action
|
||||
* @param string $options parameters of callback function, should be an array
|
||||
* @param mixed $default default value if callback function hasn't been defined
|
||||
* @return mixed
|
||||
*/
|
||||
function plugin_callback($type, $name, $feature, $action, $options = null, $default=null) {
|
||||
global $CFG;
|
||||
$component = clean_param($type . '_' . $name, PARAM_COMPONENT);
|
||||
if (empty($component)) {
|
||||
throw coding_exception('Invalid component used in plugin_callback():' . $type . '_' . $name);
|
||||
}
|
||||
|
||||
$name = clean_param($name, PARAM_SAFEDIR);
|
||||
$function = $name.'_'.$feature.'_'.$action;
|
||||
$file = get_component_directory($type . '_' . $name) . '/lib.php';
|
||||
|
||||
$dir = get_component_directory($component);
|
||||
if (empty($dir)) {
|
||||
throw coding_exception('Invalid component used in plugin_callback():' . $type . '_' . $name);
|
||||
}
|
||||
|
||||
// Load library and look for function
|
||||
if (file_exists($file)) {
|
||||
require_once($file);
|
||||
if (file_exists($dir.'/lib.php')) {
|
||||
require_once($dir.'/lib.php');
|
||||
}
|
||||
|
||||
if (function_exists($function)) {
|
||||
// Function exists, so just return function result
|
||||
$ret = call_user_func_array($function, (array)$options);
|
||||
|
@ -7531,24 +7594,30 @@ function plugin_callback($type, $name, $feature, $action, $options = null, $defa
|
|||
function plugin_supports($type, $name, $feature, $default = NULL) {
|
||||
global $CFG;
|
||||
|
||||
$name = clean_param($name, PARAM_SAFEDIR); //bit of extra security
|
||||
if ($type === 'mod' and $name === 'NEWMODULE') {
|
||||
//somebody forgot to rename the module template
|
||||
return false;
|
||||
}
|
||||
|
||||
$component = clean_param($type . '_' . $name, PARAM_COMPONENT);
|
||||
if (empty($component)) {
|
||||
throw coding_exception('Invalid component used in plugin_supports():' . $type . '_' . $name);
|
||||
}
|
||||
|
||||
$function = null;
|
||||
|
||||
if ($type === 'mod') {
|
||||
// we need this special case because we support subplugins in modules,
|
||||
// otherwise it would end up in infinite loop
|
||||
if ($name === 'NEWMODULE') {
|
||||
//somebody forgot to rename the module template
|
||||
return false;
|
||||
}
|
||||
if (file_exists("$CFG->dirroot/mod/$name/lib.php")) {
|
||||
include_once("$CFG->dirroot/mod/$name/lib.php");
|
||||
$function = $type.'_'.$name.'_supports';
|
||||
$function = $component.'_supports';
|
||||
if (!function_exists($function)) {
|
||||
// legacy non-frankenstyle function name
|
||||
$function = $name.'_supports';
|
||||
}
|
||||
} else {
|
||||
// invalid module
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -7558,7 +7627,7 @@ function plugin_supports($type, $name, $feature, $default = NULL) {
|
|||
}
|
||||
if (file_exists("$path/lib.php")) {
|
||||
include_once("$path/lib.php");
|
||||
$function = $type.'_'.$name.'_supports';
|
||||
$function = $component.'_supports';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ final class portfolio_admin_form extends moodleform {
|
|||
$mform->addElement('hidden', 'visible', $this->visible);
|
||||
$mform->setType('visible', PARAM_INT);
|
||||
$mform->addElement('hidden', 'plugin', $this->plugin);
|
||||
$mform->setType('plugin', PARAM_SAFEDIR);
|
||||
$mform->setType('plugin', PARAM_PLUGIN);
|
||||
|
||||
if (!$this->instance) {
|
||||
$insane = portfolio_instance_sanity_check($this->instance);
|
||||
|
|
|
@ -712,7 +712,7 @@ if (!empty($CFG->profilingenabled)) {
|
|||
// Process theme change in the URL.
|
||||
if (!empty($CFG->allowthemechangeonurl) and !empty($_GET['theme'])) {
|
||||
// we have to use _GET directly because we do not want this to interfere with _POST
|
||||
$urlthemename = optional_param('theme', '', PARAM_SAFEDIR);
|
||||
$urlthemename = optional_param('theme', '', PARAM_PLUGIN);
|
||||
try {
|
||||
$themeconfig = theme_config::load($urlthemename);
|
||||
// Makes sure the theme can be loaded without errors.
|
||||
|
|
|
@ -693,6 +693,62 @@ class moodlelib_test extends UnitTestCase {
|
|||
',9789,42897');
|
||||
}
|
||||
|
||||
function test_clean_param_component() {
|
||||
// please note the cleaning of component names is very strict, no guessing here
|
||||
$this->assertIdentical(clean_param('mod_forum', PARAM_COMPONENT), 'mod_forum');
|
||||
$this->assertIdentical(clean_param('block_online_users', PARAM_COMPONENT), 'block_online_users');
|
||||
$this->assertIdentical(clean_param('block_blond_online_users', PARAM_COMPONENT), 'block_blond_online_users');
|
||||
$this->assertIdentical(clean_param('mod_something2', PARAM_COMPONENT), 'mod_something2');
|
||||
$this->assertIdentical(clean_param('forum', PARAM_COMPONENT), 'forum');
|
||||
$this->assertIdentical(clean_param('user', PARAM_COMPONENT), 'user');
|
||||
$this->assertIdentical(clean_param('rating', PARAM_COMPONENT), 'rating');
|
||||
$this->assertIdentical(clean_param('mod_2something', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('2mod_something', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('mod_something_xx', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('auth_something__xx', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('mod_Something', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('mod_somethíng', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('auth_xx-yy', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('_auth_xx', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('a2uth_xx', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('auth_xx_', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('auth_xx.old', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('_user', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('2rating', PARAM_COMPONENT), '');
|
||||
$this->assertIdentical(clean_param('user_', PARAM_COMPONENT), '');
|
||||
}
|
||||
|
||||
function test_clean_param_plugin() {
|
||||
// please note the cleaning of plugin names is very strict, no guessing here
|
||||
$this->assertIdentical(clean_param('forum', PARAM_PLUGIN), 'forum');
|
||||
$this->assertIdentical(clean_param('forum2', PARAM_PLUGIN), 'forum2');
|
||||
$this->assertIdentical(clean_param('online_users', PARAM_PLUGIN), 'online_users');
|
||||
$this->assertIdentical(clean_param('blond_online_users', PARAM_PLUGIN), 'blond_online_users');
|
||||
$this->assertIdentical(clean_param('online__users', PARAM_PLUGIN), '');
|
||||
$this->assertIdentical(clean_param('forum ', PARAM_PLUGIN), '');
|
||||
$this->assertIdentical(clean_param('forum.old', PARAM_PLUGIN), '');
|
||||
$this->assertIdentical(clean_param('xx-yy', PARAM_PLUGIN), '');
|
||||
$this->assertIdentical(clean_param('2xx', PARAM_PLUGIN), '');
|
||||
$this->assertIdentical(clean_param('Xx', PARAM_PLUGIN), '');
|
||||
$this->assertIdentical(clean_param('_xx', PARAM_PLUGIN), '');
|
||||
$this->assertIdentical(clean_param('xx_', PARAM_PLUGIN), '');
|
||||
}
|
||||
|
||||
function test_clean_param_area() {
|
||||
// please note the cleaning of area names is very strict, no guessing here
|
||||
$this->assertIdentical(clean_param('something', PARAM_AREA), 'something');
|
||||
$this->assertIdentical(clean_param('something2', PARAM_AREA), 'something2');
|
||||
$this->assertIdentical(clean_param('some_thing', PARAM_AREA), 'some_thing');
|
||||
$this->assertIdentical(clean_param('some_thing_xx', PARAM_AREA), 'some_thing_xx');
|
||||
$this->assertIdentical(clean_param('_something', PARAM_AREA), '');
|
||||
$this->assertIdentical(clean_param('something_', PARAM_AREA), '');
|
||||
$this->assertIdentical(clean_param('2something', PARAM_AREA), '');
|
||||
$this->assertIdentical(clean_param('Something', PARAM_AREA), '');
|
||||
$this->assertIdentical(clean_param('some-thing', PARAM_AREA), '');
|
||||
$this->assertIdentical(clean_param('somethííng', PARAM_AREA), '');
|
||||
$this->assertIdentical(clean_param('something.x', PARAM_AREA), '');
|
||||
}
|
||||
|
||||
function test_clean_param_text() {
|
||||
$this->assertEqual(PARAM_TEXT, PARAM_MULTILANG);
|
||||
//standard
|
||||
|
|
|
@ -276,14 +276,11 @@ function upgrade_plugins($type, $startcallback, $endcallback, $verbose) {
|
|||
$plugs = get_plugin_list($type);
|
||||
|
||||
foreach ($plugs as $plug=>$fullplug) {
|
||||
$component = $type.'_'.$plug; // standardised plugin name
|
||||
$component = clean_param($type.'_'.$plug, PARAM_COMPONENT); // standardised plugin name
|
||||
|
||||
// check plugin dir is valid name
|
||||
$cplug = strtolower($plug);
|
||||
$cplug = clean_param($cplug, PARAM_SAFEDIR);
|
||||
$cplug = str_replace('-', '', $cplug);
|
||||
if ($plug !== $cplug) {
|
||||
throw new plugin_defective_exception($component, 'Invalid plugin directory name.');
|
||||
if (empty($component)) {
|
||||
throw new plugin_defective_exception($type.'_'.$plug, 'Invalid plugin directory name.');
|
||||
}
|
||||
|
||||
if (!is_readable($fullplug.'/version.php')) {
|
||||
|
@ -430,15 +427,11 @@ function upgrade_plugins_modules($startcallback, $endcallback, $verbose) {
|
|||
continue;
|
||||
}
|
||||
|
||||
$component = 'mod_'.$mod;
|
||||
$component = clean_param('mod_'.$mod, PARAM_COMPONENT);
|
||||
|
||||
// check module dir is valid name
|
||||
$cmod = strtolower($mod);
|
||||
$cmod = clean_param($cmod, PARAM_SAFEDIR);
|
||||
$cmod = str_replace('-', '', $cmod);
|
||||
$cmod = str_replace('_', '', $cmod); // modules MUST not have '_' in name and never will, sorry
|
||||
if ($mod !== $cmod) {
|
||||
throw new plugin_defective_exception($component, 'Invalid plugin directory name.');
|
||||
if (empty($component)) {
|
||||
throw new plugin_defective_exception('mod_'.$mod, 'Invalid plugin directory name.');
|
||||
}
|
||||
|
||||
if (!is_readable($fullmod.'/version.php')) {
|
||||
|
@ -593,18 +586,15 @@ function upgrade_plugins_blocks($startcallback, $endcallback, $verbose) {
|
|||
$first_install = ($DB->count_records('block_instances') == 0);
|
||||
}
|
||||
|
||||
if ($blockname == 'NEWBLOCK') { // Someone has unzipped the template, ignore it
|
||||
if ($blockname === 'NEWBLOCK') { // Someone has unzipped the template, ignore it
|
||||
continue;
|
||||
}
|
||||
|
||||
$component = 'block_'.$blockname;
|
||||
$component = clean_param('block_'.$blockname, PARAM_COMPONENT);
|
||||
|
||||
// check block dir is valid name
|
||||
$cblockname = strtolower($blockname);
|
||||
$cblockname = clean_param($cblockname, PARAM_SAFEDIR);
|
||||
$cblockname = str_replace('-', '', $cblockname);
|
||||
if ($blockname !== $cblockname) {
|
||||
throw new plugin_defective_exception($component, 'Invalid plugin directory name.');
|
||||
if (empty($component)) {
|
||||
throw new plugin_defective_exception('block_'.$blockname, 'Invalid plugin directory name.');
|
||||
}
|
||||
|
||||
if (!is_readable($fullblock.'/version.php')) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue