Merge branch 'w38_MDL-29401_m22_frankenstyle' of git://github.com/skodak/moodle

This commit is contained in:
Eloy Lafuente (stronk7) 2011-09-27 00:00:20 +02:00
commit e135797586
50 changed files with 267 additions and 142 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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');
}

View file

@ -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';
}
}

View file

@ -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);

View file

@ -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.

View file

@ -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

View file

@ -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')) {