diff --git a/application/dashlet.class.inc.php b/application/dashlet.class.inc.php
index a298a5069..43b06b666 100644
--- a/application/dashlet.class.inc.php
+++ b/application/dashlet.class.inc.php
@@ -667,7 +667,7 @@ class DashletUnknown extends Dashlet
*/
public function GetPropertiesFields(DesignerForm $oForm)
{
- $oField = new DesignerLongTextField('xml', Dict::S('UI:DashletUnknown:Prop-XMLConfiguration'), $this->sOriginalDashletXML);
+ $oField = new DesignerXMLField('xml', Dict::S('UI:DashletUnknown:Prop-XMLConfiguration'), $this->sOriginalDashletXML);
$oForm->AddField($oField);
}
diff --git a/application/forms.class.inc.php b/application/forms.class.inc.php
index 889efe04d..ec952e0a3 100644
--- a/application/forms.class.inc.php
+++ b/application/forms.class.inc.php
@@ -1110,13 +1110,41 @@ $('#$sId').on('change keyup validate', function() { ValidateWithPattern('$sId',
}
EOF
);
- $sValue = "";
+ $sValue = "";
}
else {
- $sValue = "
".utils::EscapeHtml($this->defaultValue)."
";
+ $sValue = "".$this->PrepareValueForRendering()."
";
}
return array('label' => $this->sLabel, 'value' => $sValue);
}
+
+ /**
+ * @return string|null The value itself as expected for rendering. May it be encoded, escaped or else.
+ * @since 3.1.0 N°6405
+ */
+ protected function PrepareValueForRendering(): ?string
+ {
+ return utils::EscapeHtml($this->defaultValue);
+ }
+}
+
+/**
+ * Class DesignerXMLField
+ *
+ * Field to display XML content
+ *
+ * @author Guillaume Lajarige
+ * @since 3.1.0 N°6405
+ */
+class DesignerXMLField extends DesignerLongTextField
+{
+ /**
+ * @inheritDoc
+ */
+ protected function PrepareValueForRendering(): ?string
+ {
+ return utils::EscapeHtml($this->defaultValue, true);
+ }
}
class DesignerIntegerField extends DesignerFormField
diff --git a/application/utils.inc.php b/application/utils.inc.php
index 87e4f7dc0..575da4fa1 100644
--- a/application/utils.inc.php
+++ b/application/utils.inc.php
@@ -1970,6 +1970,7 @@ SQL;
/**
* @param string $sValue
+ * @param bool $bDoubleEncode Whether to double encode the value or not
*
* @return string passed value with only characters having a special meaning in HTML escaped as entities
* Since 3.0.0 we were using for this {@link HtmlEntities} but it was overkill and leads to double escaping !
@@ -1977,14 +1978,15 @@ SQL;
* @uses \htmlspecialchars()
* @link https://www.php.net/manual/fr/function.htmlspecialchars.php
* @since 3.0.0 N°3623
+ * @since 3.1.0 N°6405 Add $bDoubleEncode parameter
*/
- public static function EscapeHtml($sValue)
+ public static function EscapeHtml($sValue, bool $bDoubleEncode = false)
{
return htmlspecialchars(
$sValue ?? '',
ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5,
WebPage::PAGES_CHARSET,
- false
+ $bDoubleEncode
);
}
diff --git a/tests/php-unit-tests/unitary-tests/application/DesignerFormFieldTest.php b/tests/php-unit-tests/unitary-tests/application/DesignerFormFieldTest.php
new file mode 100644
index 000000000..eae8975eb
--- /dev/null
+++ b/tests/php-unit-tests/unitary-tests/application/DesignerFormFieldTest.php
@@ -0,0 +1,82 @@
+
+ *
+ */
+
+namespace Combodo\iTop\Test\UnitTest\Application;
+
+use Combodo\iTop\Test\UnitTest\ItopTestCase;
+use DesignerXMLField;
+use utils;
+
+/**
+ * @covers DesignerFormField
+ */
+class DesignerFormFieldTest extends ItopTestCase
+{
+ /**
+ * @param string $sFieldFQCN
+ * @param string $sInputValue
+ * @param string $sExpectedValue
+ *
+ * @return void
+ * @throws \ReflectionException
+ * @covers DesignerLongTextField::PrepareValueForRendering
+ * @dataProvider PrepareValueForRenderingProvider
+ */
+ public function testPrepareValueForRendering(string $sFieldFQCN, string $sInputValue, string $sExpectedValue)
+ {
+ $oField = new $sFieldFQCN('field_code', 'Field label', $sInputValue);
+
+ $sTestedValue = $this->InvokeNonPublicMethod($sFieldFQCN, 'PrepareValueForRendering', $oField, []);
+ $this->assertEquals($sExpectedValue, $sTestedValue);
+ }
+
+ public function PrepareValueForRenderingProvider(): array
+ {
+ return [
+ 'DesignerLongTextField should not double encode XML' => [
+ '\\DesignerLongTextField',
+ <<
+ Foo & Bar
+
+XML,
+ << [
+ '\\DesignerXMLField',
+ <<
+ Foo & Bar
+
+XML,
+ << ['abcdefghijklmnop', null],
'&' => ['abcdefghijklmnop&0123456789', 'abcdefghijklmnop&0123456789'],
- ['"double quotes"', '"double quotes"'],
- ["'simple quotes'", ''simple quotes''],
+ 'double quotes' => ['"double quotes"', '"double quotes"'],
+ 'simple quotes' => ["'simple quotes'", ''simple quotes''],
+ 'no double encode' => [
+ 'Foo & Bar',
+ '<root><title>Foo & Bar</title></root>'
+ ],
+ 'double encode forced (for XML mostly)' => [
+ 'Foo & Bar',
+ '<root><title>Foo & Bar</title></root>',
+ true
+ ],
];
}
}