mirror of
https://github.com/moodle/moodle.git
synced 2025-08-04 16:36:37 +02:00
trusttext:
* proposed by Martin Dougiamas * implemented by skodak Usage: 1/ change enabletrusttext to yes in site settings (it is off by default) or set it in config.php 2/ assign moodle/site:trustcontent capability to users whose text submitted in glossary entries, comments, forum posts etc. should not be cleaned == they can use javascript or any other forbidden tags in glossary and forums... done: * core * glossary (without proper upgrade) to do: * data cleaning in upgrades * forum, blocks and some other places (MD decides)
This commit is contained in:
parent
8618b509fd
commit
7d8a3cb06a
12 changed files with 193 additions and 33 deletions
|
@ -225,6 +225,9 @@ class configvarrss extends configvar {
|
|||
$permissions['allowobjectembed'] = new configvar (get_string('configallowobjectembed', 'admin'),
|
||||
choose_from_menu ($noyesoptions, 'allowobjectembed', $config->allowobjectembed, '', '', '', true) );
|
||||
|
||||
/// enabletrusttext
|
||||
$permissions['enabletrusttext'] = new configvar (get_string('configenabletrusttext', 'admin'),
|
||||
choose_from_menu ($noyesoptions, 'enabletrusttext', $config->enabletrusttext, '', '', '', true) );
|
||||
|
||||
unset($options);
|
||||
$options['none'] = 'No courses';
|
||||
|
|
|
@ -77,6 +77,7 @@ $temp->add(new admin_setting_configcheckbox('opentogoogle', get_string('opentogo
|
|||
$temp->add(new admin_setting_configtext('maxbytes', get_string('maxbytes', 'admin'), get_string('configmaxbytes', 'admin'), PARAM_INT));
|
||||
$temp->add(new admin_setting_configcheckbox('messaging', get_string('messaging', 'admin'), get_string('configmessaging','admin')));
|
||||
$temp->add(new admin_setting_configcheckbox('allowobjectembed', get_string('allowobjectembed', 'admin'), get_string('configallowobjectembed', 'admin')));
|
||||
$temp->add(new admin_setting_configcheckbox('enabletrusttext', get_string('enabletrusttext', 'admin'), get_string('configenabletrusttext', 'admin')));
|
||||
$temp->add(new admin_setting_configselect('maxeditingtime', get_string('maxeditingtime','admin'), get_string('configmaxeditingtime','admin'), array(60 => get_string('numminutes', '', 1),
|
||||
300 => get_string('numminutes', '', 5),
|
||||
900 => get_string('numminutes', '', 15),
|
||||
|
|
|
@ -186,6 +186,20 @@ $moodle_capabilities = array(
|
|||
)
|
||||
),
|
||||
|
||||
'moodle/site:trustcontent' => array(
|
||||
|
||||
'captype' => 'write',
|
||||
'contextlevel' => CONTEXT_SYSTEM,
|
||||
'legacy' => array(
|
||||
'guest' => CAP_PREVENT,
|
||||
'student' => CAP_PREVENT,
|
||||
'teacher' => CAP_PREVENT,
|
||||
'editingteacher' => CAP_ALLOW,
|
||||
'coursecreator' => CAP_ALLOW,
|
||||
'admin' => CAP_ALLOW
|
||||
)
|
||||
),
|
||||
|
||||
'moodle/user:create' => array(
|
||||
|
||||
'captype' => 'write',
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
'enablecourserequests' => 0,
|
||||
'enablerssfeeds' => 0,
|
||||
'enablestats' => 0,
|
||||
'enabletrusttext' => 0,
|
||||
'enrol' => 'internal',
|
||||
'extendedusernamechars' => false,
|
||||
'editorbackgroundcolor' => '#ffffff',
|
||||
|
|
126
lib/weblib.php
126
lib/weblib.php
|
@ -72,6 +72,11 @@ define('FORMAT_WIKI', '3'); // Wiki-formatted text
|
|||
*/
|
||||
define('FORMAT_MARKDOWN', '4'); // Markdown-formatted text http://daringfireball.net/projects/markdown/
|
||||
|
||||
/**
|
||||
* TRUSTTEXT marker - if present in text, text cleaning should be bypassed
|
||||
*/
|
||||
define('TRUSTTEXT', '#####TRUSTTEXT#####');
|
||||
|
||||
|
||||
/**
|
||||
* Allowed tags - string of html tags that can be tested against for safe html tags
|
||||
|
@ -1234,10 +1239,14 @@ function format_text_menu() {
|
|||
* @return string
|
||||
* @todo Finish documenting this function
|
||||
*/
|
||||
function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL ) {
|
||||
function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL) {
|
||||
|
||||
global $CFG, $course;
|
||||
|
||||
if (!isset($options->trusttext)) {
|
||||
$options->trusttext = false;
|
||||
}
|
||||
|
||||
if (!isset($options->noclean)) {
|
||||
$options->noclean=false;
|
||||
}
|
||||
|
@ -1262,7 +1271,7 @@ function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL
|
|||
|
||||
if (!empty($CFG->cachetext)) {
|
||||
$time = time() - $CFG->cachetext;
|
||||
$md5key = md5($text.'-'.$courseid.$options->noclean.$options->smiley.$options->filter.$options->para.$options->newlines.$format.current_language().$courseid);
|
||||
$md5key = md5($text.'-'.$courseid.$options->noclean.$options->smiley.$options->filter.$options->para.$options->newlines.$format.current_language().$courseid.$options->trusttext);
|
||||
if ($oldcacheitem = get_record_sql('SELECT * FROM '.$CFG->prefix.'cache_text WHERE md5key = \''.$md5key.'\'', true)) {
|
||||
if ($oldcacheitem->timemodified >= $time) {
|
||||
return $oldcacheitem->formattedtext;
|
||||
|
@ -1270,17 +1279,31 @@ function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL
|
|||
}
|
||||
}
|
||||
|
||||
// trusttext overrides the noclean option!
|
||||
if ($options->trusttext) {
|
||||
if (trusttext_present($text)) {
|
||||
$text = trusttext_strip($text);
|
||||
if (!empty($CFG->enabletrusttext)) {
|
||||
$options->noclean = true;
|
||||
} else {
|
||||
$options->noclean = false;
|
||||
}
|
||||
} else {
|
||||
$options->noclean = false;
|
||||
}
|
||||
}
|
||||
|
||||
$CFG->currenttextiscacheable = true; // Default status - can be changed by any filter
|
||||
|
||||
switch ($format) {
|
||||
case FORMAT_HTML:
|
||||
if (!empty($options->smiley)) {
|
||||
if ($options->smiley) {
|
||||
replace_smilies($text);
|
||||
}
|
||||
if (empty($options->noclean)) {
|
||||
if (!$options->noclean) {
|
||||
$text = clean_text($text, $format);
|
||||
}
|
||||
if (!empty($options->filter)) {
|
||||
if ($options->filter) {
|
||||
$text = filter_text($text, $courseid);
|
||||
}
|
||||
break;
|
||||
|
@ -1302,25 +1325,25 @@ function format_text($text, $format=FORMAT_MOODLE, $options=NULL, $courseid=NULL
|
|||
|
||||
case FORMAT_MARKDOWN:
|
||||
$text = markdown_to_html($text);
|
||||
if (!empty($options->smiley)) {
|
||||
if ($options->smiley) {
|
||||
replace_smilies($text);
|
||||
}
|
||||
if (empty($options->noclean)) {
|
||||
if (!$options->noclean) {
|
||||
$text = clean_text($text, $format);
|
||||
}
|
||||
|
||||
if (!empty($options->filter)) {
|
||||
if ($options->filter) {
|
||||
$text = filter_text($text, $courseid);
|
||||
}
|
||||
break;
|
||||
|
||||
default: // FORMAT_MOODLE or anything else
|
||||
$text = text_to_html($text, $options->smiley, $options->para, $options->newlines);
|
||||
if (empty($options->noclean)) {
|
||||
if (!$options->noclean) {
|
||||
$text = clean_text($text, $format);
|
||||
}
|
||||
|
||||
if (!empty($options->filter)) {
|
||||
if ($options->filter) {
|
||||
$text = filter_text($text, $courseid);
|
||||
}
|
||||
break;
|
||||
|
@ -1475,7 +1498,6 @@ function format_text_email($text, $format) {
|
|||
* @todo Finish documenting this function
|
||||
*/
|
||||
function filter_text($text, $courseid=NULL) {
|
||||
|
||||
global $CFG;
|
||||
|
||||
require_once($CFG->libdir.'/filterlib.php');
|
||||
|
@ -1499,6 +1521,88 @@ function filter_text($text, $courseid=NULL) {
|
|||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the text marked as trusted?
|
||||
*
|
||||
* @param string $text text to be searched for TRUSTTEXT marker
|
||||
* @return boolean
|
||||
*/
|
||||
function trusttext_present($text) {
|
||||
if (strpos($text, TRUSTTEXT) !== FALSE) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This funtion MUST be called before the cleaning or any other
|
||||
* function that modifies the data! We do not know the origin of trusttext
|
||||
* in database, if it gets there in tweaked form we must not convert it
|
||||
* to supported form!!!
|
||||
*
|
||||
* Please be carefull not to use stripslashes on data from database
|
||||
* or twice stripslashes when processing data recieved from user.
|
||||
*
|
||||
* @param string $text text that may contain TRUSTTEXT marker
|
||||
* @return text without any TRUSTTEXT marker
|
||||
*/
|
||||
function trusttext_strip($text) {
|
||||
global $CFG;
|
||||
|
||||
while (true) { //removing nested TRUSTTEXT
|
||||
$orig = $text;
|
||||
$text = str_replace(TRUSTTEXT, '', $text);
|
||||
if (strcmp($orig, $text) === 0) {
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark text as trusted, such text may contain any HTML tags because the
|
||||
* normal text cleaning will be bypassed.
|
||||
* Please make sure that the text comes from trusted user before storing
|
||||
* it into database!
|
||||
*/
|
||||
function trusttext_mark($text) {
|
||||
global $CFG;
|
||||
if (!empty($CFG->enabletrusttext) and (strpos($text, TRUSTTEXT) === FALSE)) {
|
||||
return TRUSTTEXT.$text;
|
||||
} else {
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
function trusttext_after_edit(&$text, $context) {
|
||||
if (has_capability('moodle/site:trustcontent', $context)) {
|
||||
$text = trusttext_mark($text);
|
||||
} else {
|
||||
$text = trusttext_strip($text);
|
||||
}
|
||||
}
|
||||
|
||||
function trusttext_prepare_edit(&$text, &$format, $usehtmleditor, $context) {
|
||||
global $CFG;
|
||||
|
||||
$options = new object();
|
||||
$options->smiley = false;
|
||||
$options->filter = false;
|
||||
if (!empty($CFG->enabletrusttext)
|
||||
and has_capability('moodle/site:trustcontent', $context)
|
||||
and trusttext_present($text)) {
|
||||
$options->noclean = true;
|
||||
} else {
|
||||
$options->noclean = false;
|
||||
}
|
||||
$text = trusttext_strip($text);
|
||||
if ($usehtmleditor) {
|
||||
$text = format_text($text, $format, $options);
|
||||
$format = FORMAT_HTML;
|
||||
} else if (!$options->noclean){
|
||||
$text = clean_text($text, $format);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given raw text (eg typed in by a user), this function cleans it up
|
||||
* and removes any nasty tags that could mess up Moodle pages.
|
||||
|
|
|
@ -2,13 +2,9 @@
|
|||
if (!isset($form->format)) {
|
||||
$form->format = $defaultformat;
|
||||
}
|
||||
if ($usehtmleditor) { //clean and convert before editing
|
||||
$options = new object();
|
||||
$options->smiley = false;
|
||||
$options->filter = false;
|
||||
$form->text = format_text($form->text, $form->format, $options);
|
||||
$form->format = FORMAT_HTML;
|
||||
}
|
||||
|
||||
trusttext_prepare_edit($form->text, $form->format, $usehtmleditor, $context)
|
||||
|
||||
?>
|
||||
<form name="form" method="post" action="comment.php">
|
||||
<table class="generalbox">
|
||||
|
|
|
@ -134,7 +134,7 @@
|
|||
}
|
||||
|
||||
if ( $confirm and $form = data_submitted() ) {
|
||||
//$form->text = clean_text($form->text, $form->format);
|
||||
trusttext_after_edit($form->text, $context);
|
||||
|
||||
$newentry->entryid = $entry->id;
|
||||
$newentry->comment = $form->text;
|
||||
|
|
|
@ -2,13 +2,9 @@
|
|||
if (!isset($newentry->format)) {
|
||||
$newentry->format = $defaultformat;
|
||||
}
|
||||
if ($usehtmleditor) { //clean and convert before editing
|
||||
$options = new object();
|
||||
$options->smiley = false;
|
||||
$options->filter = false;
|
||||
$newentry->definition = format_text($newentry->definition, $newentry->format, $options);
|
||||
$newentry->format = FORMAT_HTML;
|
||||
}
|
||||
|
||||
trusttext_prepare_edit($newentry->definition, $newentry->format, $usehtmleditor, $context)
|
||||
|
||||
?>
|
||||
<form name="form" method="post" action="edit.php" enctype="multipart/form-data">
|
||||
<table border="0" cellpadding="5">
|
||||
|
|
|
@ -43,6 +43,8 @@ if (!$glossary->studentcanpost && !has_capability('mod/glossary:manageentries',
|
|||
}
|
||||
if ( $confirm ) {
|
||||
$form = data_submitted();
|
||||
trusttext_after_edit($form->text, $context);
|
||||
|
||||
if ( !isset($form->usedynalink) ) {
|
||||
$form->usedynalink = 0;
|
||||
}
|
||||
|
@ -245,6 +247,7 @@ if ( $confirm ) {
|
|||
$newentry->userid = $form->userid;
|
||||
$newentry->timecreated = $form->timecreated;
|
||||
|
||||
|
||||
if ( $aliases = get_records("glossary_alias","entryid",$e) ) {
|
||||
foreach ($aliases as $alias) {
|
||||
$newentry->aliases .= $alias->alias . "\n";
|
||||
|
@ -332,7 +335,7 @@ $tab = GLOSSARY_ADDENTRY_VIEW;
|
|||
include("tabs.html");
|
||||
|
||||
if (!$e) {
|
||||
require_capability('glossary_write', $context);
|
||||
require_capability('mod/glossary:write', $context);
|
||||
}
|
||||
|
||||
include("edit.html");
|
||||
|
|
|
@ -212,7 +212,7 @@
|
|||
$xmlentry = $xmlentries[$i];
|
||||
unset($newentry);
|
||||
$newentry->concept = trim(addslashes($xmlentry['#']['CONCEPT'][0]['#']));
|
||||
$newentry->definition = addslashes($xmlentry['#']['DEFINITION'][0]['#']);
|
||||
$newentry->definition = trusttext_strip(addslashes($xmlentry['#']['DEFINITION'][0]['#']));
|
||||
if ( isset($xmlentry['#']['CASESENSITIVE'][0]['#']) ) {
|
||||
$newentry->casesensitive = addslashes($xmlentry['#']['CASESENSITIVE'][0]['#']);
|
||||
} else {
|
||||
|
|
|
@ -588,13 +588,36 @@ function glossary_print_entry($course, $cm, $glossary, $entry, $mode='',$hook=''
|
|||
//Default (old) print format used if custom function doesn't exist in format
|
||||
function glossary_print_entry_default ($entry) {
|
||||
echo '<b>'. strip_tags($entry->concept) . ': </b>';
|
||||
|
||||
$definition = $entry->definition;
|
||||
|
||||
// always detect and strip TRUSTTEXT marker before processing and add+strip it afterwards!
|
||||
if (trusttext_present($definition)) {
|
||||
$ttpresent = true;
|
||||
$definition = trusttext_strip($definition);
|
||||
} else {
|
||||
$ttpresent = false;
|
||||
}
|
||||
|
||||
$definition = '<span class="nolink">' . strip_tags($definition) . '</span>';
|
||||
|
||||
// reconstruct the TRUSTTEXT properly after processing
|
||||
if ($ttpresent) {
|
||||
$definition = trusttext_mark($definition);
|
||||
} else {
|
||||
$definition = trusttext_strip($definition); //make 100% sure TRUSTTEXT marker was not created
|
||||
}
|
||||
|
||||
$options = new object();
|
||||
$options->para = false;
|
||||
$definition = format_text('<span class="nolink">' . strip_tags($entry->definition) . '</span>', $entry->format,$options);
|
||||
$options->trusttext = true;
|
||||
$definition = format_text($definition, $entry->format, $options);
|
||||
echo ($definition);
|
||||
echo '<br /><br />';
|
||||
}
|
||||
|
||||
function glossary_print_entry_concept($entry) {
|
||||
$options = new object();
|
||||
$options->para = false;
|
||||
$text = format_text('<span class="nolink">' . $entry->concept . '</span>', FORMAT_MOODLE, $options);
|
||||
if (!empty($entry->highlight)) {
|
||||
|
@ -607,6 +630,14 @@ function glossary_print_entry_definition($entry) {
|
|||
|
||||
$definition = $entry->definition;
|
||||
|
||||
// always detect and strip TRUSTTEXT marker before processing and add+strip it afterwards!
|
||||
if (trusttext_present($definition)) {
|
||||
$ttpresent = true;
|
||||
$definition = trusttext_strip($definition);
|
||||
} else {
|
||||
$ttpresent = false;
|
||||
}
|
||||
|
||||
$links = array();
|
||||
$tags = array();
|
||||
$urls = array();
|
||||
|
@ -702,9 +733,18 @@ function glossary_print_entry_definition($entry) {
|
|||
$definition = str_replace(array_keys($links),$links,$definition);
|
||||
}
|
||||
|
||||
$options = new object();
|
||||
$options->para = false;
|
||||
$options->trusttext = true;
|
||||
|
||||
$text = format_text($definition, $entry->format,$options);
|
||||
// reconstruct the TRUSTTEXT properly after processing
|
||||
if ($ttpresent) {
|
||||
$definition = trusttext_mark($definition);
|
||||
} else {
|
||||
$definition = trusttext_strip($definition); //make 100% sure TRUSTTEXT marker was not created
|
||||
}
|
||||
|
||||
$text = format_text($definition, $entry->format, $options);
|
||||
if (!empty($entry->highlight)) {
|
||||
$text = highlight($entry->highlight, $text);
|
||||
}
|
||||
|
@ -1537,7 +1577,9 @@ function glossary_print_comment($course, $cm, $glossary, $entry, $comment) {
|
|||
echo ' ';
|
||||
echo '</td><td class="entry">';
|
||||
|
||||
echo format_text($comment->comment, $comment->format);
|
||||
$options = new object();
|
||||
$options->trusttext = true;
|
||||
echo format_text($comment->comment, $comment->format, $options);
|
||||
|
||||
echo '<div class="icons commands">';
|
||||
|
||||
|
@ -1692,7 +1734,7 @@ function glossary_generate_export_file($glossary, $hook = "", $hook = 0) {
|
|||
if ( $entry->approved and $permissiongranted ) {
|
||||
$co .= glossary_start_tag("ENTRY",3,true);
|
||||
$co .= glossary_full_tag("CONCEPT",4,false,trim($entry->concept));
|
||||
$co .= glossary_full_tag("DEFINITION",4,false,$entry->definition);
|
||||
$co .= glossary_full_tag("DEFINITION",4,false,trusttext_strip($entry->definition));
|
||||
$co .= glossary_full_tag("FORMAT",4,false,$entry->format);
|
||||
$co .= glossary_full_tag("USEDYNALINK",4,false,$entry->usedynalink);
|
||||
$co .= glossary_full_tag("CASESENSITIVE",4,false,$entry->casesensitive);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// This is compared against the values stored in the database to determine
|
||||
// whether upgrades should be performed (see lib/db/*.php)
|
||||
|
||||
$version = 2006082300; // YYYYMMDD = date
|
||||
$version = 2006082600; // YYYYMMDD = date
|
||||
// XY = increments within a single day
|
||||
|
||||
$release = '1.7 dev'; // Human-friendly version name
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue