From 68b29e13e2e308296a14936e8162211a681da1cf Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Tue, 10 Feb 2015 15:32:44 +1300 Subject: [PATCH] BUG Use correct api for assigning field value BUG Fix encoding of cms add-option in js ENHANCEMENT Sanitise literal HTML content --- code/model/UserDefinedForm.php | 76 +++++++++---------- .../model/formfields/EditableLiteralField.php | 62 ++++++++++++++- javascript/UserForm.js | 13 +++- tests/EditableLiteralFieldTest.php | 38 ++++++++++ 4 files changed, 143 insertions(+), 46 deletions(-) create mode 100644 tests/EditableLiteralFieldTest.php diff --git a/code/model/UserDefinedForm.php b/code/model/UserDefinedForm.php index 1ffb545..82e817b 100755 --- a/code/model/UserDefinedForm.php +++ b/code/model/UserDefinedForm.php @@ -527,7 +527,7 @@ class UserDefinedForm_Controller extends Page_Controller { return $form; } - + /** * Get the form fields for the form on this page. Can modify this FieldSet * by using {@link updateFormFields()} on an {@link Extension} subclass which @@ -537,46 +537,44 @@ class UserDefinedForm_Controller extends Page_Controller { */ public function getFormFields() { $fields = new FieldList(); - - if($this->Fields()) { - foreach($this->Fields() as $editableField) { - // get the raw form field from the editable version - $field = $editableField->getFormField(); - if(!$field) break; - - // set the error / formatting messages - $field->setCustomValidationMessage($editableField->getErrorMessage()); - // set the right title on this field - if($right = $editableField->getSetting('RightTitle')) { - $field->setRightTitle($right); - } - - // if this field is required add some - if($editableField->Required) { - $field->addExtraClass('requiredField'); - - if($identifier = UserDefinedForm::config()->required_identifier) { - - $title = $field->Title() ." ". $identifier . ""; - $field->setTitle($title); - } - } - // if this field has an extra class - if($editableField->getSetting('ExtraClass')) { - $field->addExtraClass(Convert::raw2att( - $editableField->getSetting('ExtraClass') - )); - } - - // set the values passed by the url to the field - $request = $this->getRequest(); - if($var = $request->getVar($field->name)) { - $field->value = Convert::raw2att($var); - } - - $fields->push($field); + $editableFields = $this->Fields(); + if($editableFields) foreach($editableFields as $editableField) { + // get the raw form field from the editable version + $field = $editableField->getFormField(); + if(!$field) break; + + // set the error / formatting messages + $field->setCustomValidationMessage($editableField->getErrorMessage()); + + // set the right title on this field + if($right = $editableField->getSetting('RightTitle')) { + // Since this field expects raw html, safely escape the user data prior + $field->setRightTitle(Convert::raw2xml($right)); } + + // if this field is required add some + if($editableField->Required) { + $field->addExtraClass('requiredField'); + + if($identifier = UserDefinedForm::config()->required_identifier) { + + $title = $field->Title() ." ". $identifier . ""; + $field->setTitle($title); + } + } + // if this field has an extra class + if($extraClass = $editableField->getSetting('ExtraClass')) { + $field->addExtraClass(Convert::raw2att($extraClass)); + } + + // set the values passed by the url to the field + $request = $this->getRequest(); + if($value = $request->getVar($field->getName())) { + $field->setValue($value); + } + + $fields->push($field); } $this->extend('updateFormFields', $fields); diff --git a/code/model/formfields/EditableLiteralField.php b/code/model/formfields/EditableLiteralField.php index eb196b5..e4fb931 100644 --- a/code/model/formfields/EditableLiteralField.php +++ b/code/model/formfields/EditableLiteralField.php @@ -12,14 +12,70 @@ class EditableLiteralField extends EditableFormField { private static $singular_name = 'HTML Block'; private static $plural_name = 'HTML Blocks'; + + /** + * Get the name of the editor config to use for HTML sanitisation. Defaults to the active config. + * + * @var string + * @config + */ + private static $editor_config = null; + + /** + * Returns the {@see HtmlEditorConfig} instance to use for sanitisation + * + * @return HtmlEditorConfig + */ + protected function getEditorConfig() { + $editorConfig = $this->config()->editor_config; + if($editorConfig) return HtmlEditorConfig::get($editorConfig); + return HtmlEditorConfig::get_active(); + } + + /** + * Safely sanitise html content, if enabled + * + * @param string $content Raw html + * @return string Safely sanitised html + */ + protected function sanitiseContent($content) { + // Check if sanitisation is enabled + if(!HtmlEditorField::config()->sanitise_server_side) return $content; + + // Perform sanitisation + $htmlValue = Injector::inst()->create('HTMLValue', $content); + $santiser = Injector::inst()->create('HtmlEditorSanitiser', $this->getEditorConfig()); + $santiser->sanitise($htmlValue); + return $htmlValue->getContent(); + } + + /** + * Get HTML Content of this literal field + * + * @return string + */ + public function getContent() { + // Apply html editor sanitisation rules + $content = $this->getSetting('Content'); + return $this->sanitiseContent($content); + } + + /** + * Set the content with the given value + * + * @param string $content + */ + public function setContent($content) { + // Apply html editor sanitisation rules + $content = $this->sanitiseContent($content); + $this->setSetting('Content', $content); + } public function getFieldConfiguration() { - $customSettings = unserialize($this->CustomSettings); - $content = (isset($customSettings['Content'])) ? $customSettings['Content'] : ''; $textAreaField = new TextareaField( $this->getSettingName('Content'), "HTML", - $content + $this->getContent() ); $textAreaField->setRows(4); $textAreaField->setColumns(20); diff --git a/javascript/UserForm.js b/javascript/UserForm.js index fd3085a..e01d725 100644 --- a/javascript/UserForm.js +++ b/javascript/UserForm.js @@ -330,11 +330,16 @@ newRule.removeClass("hidden"); // update the fields dropdown - newRule.children("select.fieldOption").empty(); + var optionChildren = newRule.children("select.fieldOption"); + optionChildren.empty(); - $("#Fields_fields li.EditableFormField").each(function (i, domElement) { - var name = $(domElement).attr("id").split(' '); - newRule.children("select.fieldOption").append(""); + $("#Fields_fields li.EditableFormField").each(function () { + var name = $(this).attr("id").split(' '); + var option = $("") + .attr('value', name[2]) + .text($(this).find(".text").val()); + optionChildren + .append(option); }); // append to the list diff --git a/tests/EditableLiteralFieldTest.php b/tests/EditableLiteralFieldTest.php new file mode 100644 index 0000000..2a0d613 --- /dev/null +++ b/tests/EditableLiteralFieldTest.php @@ -0,0 +1,38 @@ +Welcome

Giant Robots!

'; + $safeContent = '

Welcome

Giant Robots!

'; + $field = new EditableLiteralField(); + + // Test with sanitisation enabled + Config::inst()->update('HtmlEditorField', 'sanitise_server_side', true); + $field->setContent($rawContent); + $this->assertEquals($safeContent, $field->getContent()); + + // Test with sanitisation disabled + Config::inst()->remove('HtmlEditorField', 'sanitise_server_side'); + $field->setContent($rawContent); + $this->assertEquals($rawContent, $field->getContent()); + } +}